mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Implement legacy XML-RPC interface for ACM commands.
This patch implements a (non Xen-API) legacy XML-RPC interface for the ACM commands and funnels the calls into code introduced by the Xen-API support for ACM security management. Since some of the functionality has changed, also the xm applications have changed. In particular the following old commands have been removed along with some tools the have become obsolete now: - loadpolicy (included in: setpolicy) - makepolicy (included in: setpolicy) - cfgbootpolicy (included in: setpolicy) and the following commands been introduced: - setpolicy - getpolicy - resetpolicy All tools have been adapted to work in Xen-API and legacy XML-RPC mode. Both modes support the same functionality. Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
This commit is contained in:
1 parent
c568950276
commit
0ea4d2fb34
32 files changed
+1005
-2864
No files matched your search
+30
-43
@@ -821,15 +821,13 @@ security in Xen, you must compile Xen with ACM support enabled as
|
||||
described under "Configuring Security" below. There, you will find
|
||||
also examples of each subcommand described here.
|
||||
|
||||
=item B<setpolicy> ACM I<policy> I<[--load|--boot]>
|
||||
=item B<setpolicy> ACM I<policy>
|
||||
|
||||
Makes the given ACM policy available to xend as a I<xend-managed policy>.
|
||||
The policy is compiled and a mapping (.map) as well as a binary (.bin)
|
||||
version of the policy is created. If the option I<--load> is provided
|
||||
the policy is loaded into Xen. If the option I<--boot> is provided the
|
||||
system is configure to be loaded with the policy at boot time. If these
|
||||
options are not provided with the B<setpolicy> subcommand, the
|
||||
B<activatepolicy> subcommand provides this functionality.
|
||||
version of the policy is created. The policy is loaded and the system's
|
||||
bootloader is prepared to boot the system with this policy the next time
|
||||
it is started.
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -844,16 +842,13 @@ global policy root directory.
|
||||
|
||||
=back
|
||||
|
||||
=item B<activatepolicy> I<[--load|--boot]>
|
||||
=item B<resetpolicy>
|
||||
|
||||
Activates the xend-managed policy by loading it into Xen using the
|
||||
I<--load> option or configures the system to boot with the
|
||||
xend-managed policy during the next reboot as a result of the
|
||||
I<--boot> option. The latter is only supported if the system is booted
|
||||
with the grub boot loader and the default boot title is modified.
|
||||
It copies the binary policy representation into the /boot directory and
|
||||
adds a module line specifying the binary policy to the /boot/grub/menu.lst
|
||||
or /boot/grub/grub.conf file.
|
||||
Reset the system's policy to the default state where the DEFAULT policy
|
||||
is loaded and enforced. This operation may fail if for example guest VMs are
|
||||
running and and one of them uses a different label than what Domain-0
|
||||
does. It is best to make sure that no guests are running before issuing
|
||||
this command.
|
||||
|
||||
=item B<getpolicy> [--dumpxml]
|
||||
|
||||
@@ -938,50 +933,42 @@ B<CONFIGURING SECURITY>
|
||||
|
||||
In xen_source_dir/Config.mk set the following parameter:
|
||||
|
||||
XSM_ENABLE ?= y
|
||||
ACM_SECURITY ?= y
|
||||
|
||||
Then recompile and install xen and the security tools and then reboot:
|
||||
|
||||
cd xen_source_dir/xen; make clean; make; cp xen.gz /boot;
|
||||
cd xen_source_dir/tools/security; make install;
|
||||
cd xen_source_dir; make clean; make install
|
||||
reboot into Xen
|
||||
|
||||
=back
|
||||
|
||||
B<RESETTING THE SYSTEM'S SECURITY>
|
||||
|
||||
=over 4
|
||||
|
||||
To set the system's security policy enforcement into its default state,
|
||||
the follow command can be issued. Make sure that no guests are running
|
||||
while doing this.
|
||||
|
||||
xm resetpolicy
|
||||
|
||||
After this command has successfully completed, the system's DEFAULT policy
|
||||
is enforced.
|
||||
|
||||
=back
|
||||
|
||||
B<SETTING A SECURITY POLICY>
|
||||
|
||||
=over 4
|
||||
|
||||
This step makes the policy available to xend and creates the client_v1.map and
|
||||
client_v1.bin files in /etc/xen/acm-security/policies/example/chwall_ste.
|
||||
This step sets the system's policy and automatically loads it into Xen
|
||||
for enforcement.
|
||||
|
||||
xm setpolicy ACM example.client_v1
|
||||
|
||||
=back
|
||||
|
||||
B<ACTIVATING THE XEND-MANAGED SECURITY POLICY>
|
||||
|
||||
=over 4
|
||||
|
||||
This step activates the xend-manged policy as new security policy in Xen.
|
||||
You can use the dumppolicy subcommand before and afterwards to see the
|
||||
change in the Xen policy state.
|
||||
|
||||
xm activatpolicy --load
|
||||
|
||||
=back
|
||||
|
||||
B<CONFIGURING A BOOT SECURITY POLICY>
|
||||
|
||||
=over 4
|
||||
|
||||
This configures the boot loader to load the current xend-managed policy at
|
||||
boot time. During system start, the ACM configures Xen with this policy and
|
||||
Xen enforces this policy from then on.
|
||||
|
||||
xm activatepolicy --boot
|
||||
|
||||
=back
|
||||
|
||||
B<LISTING SECURITY LABELS>
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -51,6 +51,19 @@ ACM_SCHEMA_FILE = ACM_POLICIES_DIR + "security_policy.xsd"
|
||||
ACM_LABEL_UNLABELED = "__UNLABELED__"
|
||||
ACM_LABEL_UNLABELED_DISPLAY = "unlabeled"
|
||||
|
||||
"""
|
||||
Error codes reported in when trying to test for a new policy
|
||||
These error codes are reported in an array of tuples where
|
||||
each error code is followed by a parameter describing the error
|
||||
more closely, such as a domain id.
|
||||
"""
|
||||
ACM_EVTCHN_SHARING_VIOLATION = 0x100
|
||||
ACM_GNTTAB_SHARING_VIOLATION = 0x101
|
||||
ACM_DOMAIN_LOOKUP = 0x102
|
||||
ACM_CHWALL_CONFLICT = 0x103
|
||||
ACM_SSIDREF_IN_USE = 0x104
|
||||
|
||||
|
||||
class ACMPolicy(XSPolicy):
|
||||
"""
|
||||
ACMPolicy class. Implements methods for getting information from
|
||||
@@ -228,7 +241,7 @@ class ACMPolicy(XSPolicy):
|
||||
return -xsconstants.XSERR_BAD_LABEL, errors
|
||||
|
||||
#Get binary and map from the new policy
|
||||
rc, map, bin_pol = acmpol_new.policy_create_map_and_bin()
|
||||
rc, pol_map, bin_pol = acmpol_new.policy_create_map_and_bin()
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
log.error("Could not build the map and binary policy.")
|
||||
return rc, errors
|
||||
@@ -356,7 +369,7 @@ class ACMPolicy(XSPolicy):
|
||||
pass
|
||||
return ssidref
|
||||
|
||||
def set_vm_bootlabel(self, vm_label):
|
||||
def set_vm_bootlabel(self, vm_label, remove=False):
|
||||
parms="<>"
|
||||
if vm_label != "":
|
||||
ssidref = self.vmlabel_to_ssidref(vm_label)
|
||||
@@ -367,6 +380,10 @@ class ACMPolicy(XSPolicy):
|
||||
self.get_name(),vm_label)
|
||||
else:
|
||||
ssidref = 0 #Identifier for removal
|
||||
|
||||
if remove == True:
|
||||
parms = "<>"
|
||||
|
||||
try:
|
||||
def_title = bootloader.get_default_title()
|
||||
bootloader.set_kernel_attval(def_title, "ssidref", parms)
|
||||
@@ -387,7 +404,7 @@ class ACMPolicy(XSPolicy):
|
||||
if name:
|
||||
p = name.split(".")
|
||||
path = ""
|
||||
if dotted == True:
|
||||
if dotted:
|
||||
sep = "."
|
||||
else:
|
||||
sep = "/"
|
||||
@@ -513,8 +530,8 @@ class ACMPolicy(XSPolicy):
|
||||
self.set_frompolicy_name(curpol.policy_dom_get_hdr_item("PolicyName"))
|
||||
version = curpol.policy_dom_get_hdr_item("Version")
|
||||
self.set_frompolicy_version(version)
|
||||
(maj, min) = self.__convVersionToTuple(version)
|
||||
self.set_policy_version("%s.%s" % (maj, min+1))
|
||||
(maj, minor) = self.__convVersionToTuple(version)
|
||||
self.set_policy_version("%s.%s" % (maj, minor+1))
|
||||
|
||||
#
|
||||
# Get all types that are part of a node
|
||||
@@ -877,8 +894,7 @@ class ACMPolicy(XSPolicy):
|
||||
"""
|
||||
Determine whether this policy is the active one.
|
||||
"""
|
||||
security.refresh_security_policy()
|
||||
if self.get_name() == security.active_policy:
|
||||
if self.get_name() == security.get_active_policy_name():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import os, string, re
|
||||
import threading
|
||||
import struct
|
||||
import stat
|
||||
import base64
|
||||
from xen.lowlevel import acm
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendConstants
|
||||
@@ -39,7 +40,6 @@ policy_dir_prefix = security_dir_prefix + "/policies"
|
||||
res_label_filename = policy_dir_prefix + "/resource_labels"
|
||||
boot_filename = "/boot/grub/menu.lst"
|
||||
altboot_filename = "/boot/grub/grub.conf"
|
||||
xensec_xml2bin = "/usr/sbin/xensec_xml2bin"
|
||||
xensec_tool = "/usr/sbin/xensec_tool"
|
||||
|
||||
#global patterns for map file
|
||||
@@ -49,7 +49,7 @@ secondary_entry_re = re.compile("\s*SECONDARY\s+.*", re.IGNORECASE)
|
||||
label_template_re = re.compile(".*security_label_template.xml", re.IGNORECASE)
|
||||
mapping_filename_re = re.compile(".*\.map", re.IGNORECASE)
|
||||
policy_reference_entry_re = re.compile("\s*POLICYREFERENCENAME\s+.*", re.IGNORECASE)
|
||||
vm_label_re = re.compile("\s*LABEL->SSID\s+VM\s+.*", re.IGNORECASE)
|
||||
vm_label_re = re.compile("\s*LABEL->SSID\s.+[VM|ANY]\s+.*", re.IGNORECASE)
|
||||
res_label_re = re.compile("\s*LABEL->SSID\s+RES\s+.*", re.IGNORECASE)
|
||||
all_label_re = re.compile("\s*LABEL->SSID\s+.*", re.IGNORECASE)
|
||||
access_control_re = re.compile("\s*access_control\s*=", re.IGNORECASE)
|
||||
@@ -77,9 +77,25 @@ __resfile_lock = threading.RLock()
|
||||
|
||||
log = logging.getLogger("xend.util.security")
|
||||
|
||||
|
||||
#Functions exported through XML-RPC
|
||||
xmlrpc_exports = [
|
||||
'set_resource_label',
|
||||
'get_resource_label',
|
||||
'list_labels',
|
||||
'get_labeled_resources',
|
||||
'set_policy',
|
||||
'get_policy',
|
||||
'activate_policy',
|
||||
'rm_bootpolicy',
|
||||
'get_xstype',
|
||||
'get_domain_label',
|
||||
'set_domain_label'
|
||||
]
|
||||
|
||||
# Our own exception definition. It is masked (pass) if raised and
|
||||
# whoever raises this exception must provide error information.
|
||||
class ACMError(Exception):
|
||||
class XSMError(Exception):
|
||||
def __init__(self,value):
|
||||
self.value = value
|
||||
def __str__(self):
|
||||
@@ -90,7 +106,7 @@ class ACMError(Exception):
|
||||
def err(msg):
|
||||
"""Raise ACM exception.
|
||||
"""
|
||||
raise ACMError(msg)
|
||||
raise XSMError(msg)
|
||||
|
||||
|
||||
|
||||
@@ -118,12 +134,17 @@ def refresh_security_policy():
|
||||
global active_policy
|
||||
|
||||
active_policy = 'INACCESSIBLE'
|
||||
|
||||
if os.access("/proc/xen/privcmd", os.R_OK|os.W_OK):
|
||||
try:
|
||||
active_policy = acm.policy()
|
||||
except:
|
||||
active_policy = "INACTIVE"
|
||||
|
||||
def get_active_policy_name():
|
||||
refresh_security_policy()
|
||||
return active_policy
|
||||
|
||||
# now set active_policy
|
||||
refresh_security_policy()
|
||||
|
||||
@@ -132,8 +153,7 @@ def on():
|
||||
returns none if security policy is off (not compiled),
|
||||
any string otherwise, use it: if not security.on() ...
|
||||
"""
|
||||
refresh_security_policy()
|
||||
return (active_policy not in ['INACTIVE', 'NULL'])
|
||||
return (get_active_policy_name() not in ['INACTIVE', 'NULL'])
|
||||
|
||||
|
||||
def calc_dom_ssidref_from_info(info):
|
||||
@@ -158,11 +178,10 @@ def calc_dom_ssidref_from_info(info):
|
||||
typ, policyname, vmlabel = seclab.split(":")
|
||||
if typ != xsconstants.ACM_POLICY_ID:
|
||||
raise VmError("Policy type '%s' must be changed." % typ)
|
||||
refresh_security_policy()
|
||||
if active_policy != policyname:
|
||||
if get_active_policy_name() != policyname:
|
||||
raise VmError("Active policy '%s' different than "
|
||||
"what in VM's label ('%s')." %
|
||||
(active_policy, policyname))
|
||||
(get_active_policy_name(), policyname))
|
||||
ssidref = label2ssidref(vmlabel, policyname, "dom")
|
||||
return ssidref
|
||||
else:
|
||||
@@ -180,7 +199,7 @@ def getmapfile(policyname):
|
||||
4. True if policy file is available, False otherwise
|
||||
"""
|
||||
if not policyname:
|
||||
policyname = active_policy
|
||||
policyname = get_active_policy_name()
|
||||
map_file_ok = False
|
||||
primary = None
|
||||
secondary = None
|
||||
@@ -199,8 +218,7 @@ def getmapfile(policyname):
|
||||
if not os.path.isfile(policy_filename):
|
||||
err("Policy file \'" + policy_filename + "\' not found.")
|
||||
else:
|
||||
err("Mapping file \'" + map_filename + "\' not found." +
|
||||
" Use xm makepolicy to create it.")
|
||||
err("Mapping file \'" + map_filename + "\' not found.")
|
||||
|
||||
f = open(map_filename)
|
||||
for line in f:
|
||||
@@ -221,7 +239,7 @@ def getmapfile(policyname):
|
||||
if map_file_ok and primary and secondary:
|
||||
return (primary, secondary, f, True)
|
||||
else:
|
||||
err("Mapping file inconsistencies found. Try makepolicy to create a new one.")
|
||||
err("Mapping file inconsistencies found.")
|
||||
|
||||
|
||||
|
||||
@@ -253,10 +271,10 @@ def ssidref2label(ssidref_var):
|
||||
(primary, secondary, f, pol_exists) = getmapfile(None)
|
||||
if not f:
|
||||
if (pol_exists):
|
||||
err("Mapping file for policy not found.\n" +
|
||||
"Please use makepolicy command to create mapping file!")
|
||||
err("Mapping file for policy not found.")
|
||||
else:
|
||||
err("Policy file for \'" + active_policy + "\' not found.")
|
||||
err("Policy file for \'" + get_active_policy_name() +
|
||||
"\' not found.")
|
||||
|
||||
#2. get labelnames for both ssidref parts
|
||||
pri_ssid = ssidref & 0xffff
|
||||
@@ -534,37 +552,99 @@ def hv_get_policy():
|
||||
return rc, bin_pol
|
||||
|
||||
|
||||
def make_policy(policy_name):
|
||||
policy_file = string.join(string.split(policy_name, "."), "/")
|
||||
if not os.path.isfile(policy_dir_prefix + "/" + policy_file + "-security_policy.xml"):
|
||||
err("Unknown policy \'" + policy_name + "\'")
|
||||
def set_policy(xs_type, xml, flags, overwrite):
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendXSPolicyAdmin
|
||||
xspoladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
|
||||
try:
|
||||
acmpol, rc, errors = \
|
||||
xspoladmin.add_acmpolicy_to_system(xml,
|
||||
int(flags),
|
||||
True)
|
||||
return rc, base64.b64encode(errors)
|
||||
except Exception, e:
|
||||
err(str(e))
|
||||
|
||||
(ret, output) = commands.getstatusoutput(xensec_xml2bin + " -d " + policy_dir_prefix + " " + policy_file)
|
||||
if ret:
|
||||
err("Creating policy failed:\n" + output)
|
||||
|
||||
def load_policy(policy_name):
|
||||
global active_policy
|
||||
policy_file = policy_dir_prefix + "/" + string.join(string.split(policy_name, "."), "/")
|
||||
if not os.path.isfile(policy_file + ".bin"):
|
||||
if os.path.isfile(policy_file + "-security_policy.xml"):
|
||||
err("Binary file does not exist." +
|
||||
"Please use makepolicy to build the policy binary.")
|
||||
else:
|
||||
err("Unknown Policy " + policy_name)
|
||||
def get_policy():
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendXSPolicyAdmin
|
||||
poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
|
||||
try:
|
||||
policy = poladmin.get_loaded_policy()
|
||||
if policy != None:
|
||||
return policy.toxml(), poladmin.get_policy_flags(policy)
|
||||
except Exception, e:
|
||||
err(str(e))
|
||||
return "", 0
|
||||
|
||||
#require this policy to be the first or the same as installed
|
||||
if active_policy not in ['DEFAULT', policy_name]:
|
||||
err("Active policy \'" + active_policy +
|
||||
"\' incompatible with new policy \'" + policy_name + "\'")
|
||||
(ret, output) = commands.getstatusoutput(xensec_tool + " loadpolicy " + policy_file + ".bin")
|
||||
if ret:
|
||||
err("Loading policy failed:\n" + output)
|
||||
def activate_policy(flags):
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendXSPolicyAdmin
|
||||
poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance()
|
||||
try:
|
||||
policies = poladmin.get_policies()
|
||||
if len(policies) > 0:
|
||||
flags = int(flags)
|
||||
irc = poladmin.activate_xspolicy(policies[0], flags)
|
||||
return irc
|
||||
except Exception, e:
|
||||
err("Error while activating the policy: " % str(e))
|
||||
return 0
|
||||
|
||||
|
||||
def rm_bootpolicy():
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendXSPolicyAdmin
|
||||
rc = XendXSPolicyAdmin.XSPolicyAdminInstance().rm_bootpolicy()
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
err("Error while removing boot policy: %s" % \
|
||||
str(xsconstants.xserr2string(-rc)))
|
||||
return rc
|
||||
|
||||
|
||||
def get_xstype():
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendXSPolicyAdmin
|
||||
return XendXSPolicyAdmin.XSPolicyAdminInstance().isXSEnabled()
|
||||
|
||||
|
||||
def get_domain_label(domain):
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendDomain
|
||||
dom = XendDomain.instance().domain_lookup_nr(domain)
|
||||
if dom:
|
||||
seclab = dom.get_security_label()
|
||||
return seclab
|
||||
else:
|
||||
# refresh active policy
|
||||
refresh_security_policy()
|
||||
err("Domain not found.")
|
||||
|
||||
|
||||
def set_domain_label(domain, seclab, old_seclab):
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
"""
|
||||
from xen.xend import XendDomain
|
||||
dom = XendDomain.instance().domain_lookup_nr(domain)
|
||||
if dom:
|
||||
results = dom.set_security_label(seclab, old_seclab)
|
||||
rc, errors, old_label, new_ssidref = results
|
||||
return rc, new_ssidref
|
||||
else:
|
||||
err("Domain not found.")
|
||||
|
||||
|
||||
def dump_policy():
|
||||
if active_policy in ['NULL', 'INACTIVE', 'INACCESSIBLE' ]:
|
||||
@@ -589,16 +669,32 @@ def dump_policy_file(filename, ssidref=None):
|
||||
print output
|
||||
|
||||
|
||||
def list_labels(policy_name, condition):
|
||||
if (not policy_name) and active_policy in \
|
||||
[ 'NULL', 'INACTIVE', 'DEFAULT', 'INACCESSIBLE' ]:
|
||||
err("Current policy \'" + active_policy + "\' has no labels defined.\n")
|
||||
def list_labels(policy_name, ltype):
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
|
||||
List the VM,resource or any kind of labels contained in the
|
||||
given policy. If no policy name is given, the currently
|
||||
active policy's label will be returned if they exist.
|
||||
"""
|
||||
if not policy_name:
|
||||
if active_policy in [ 'NULL', 'INACTIVE', "" ]:
|
||||
err("Current policy \'" + active_policy + "\' "
|
||||
"has no labels defined.\n")
|
||||
|
||||
if not ltype or ltype == 'dom':
|
||||
condition = vm_label_re
|
||||
elif ltype == 'res':
|
||||
condition = res_label_re
|
||||
elif ltype == 'any':
|
||||
condition = all_label_re
|
||||
else:
|
||||
err("Unknown label type \'" + ltype + "\'")
|
||||
|
||||
(primary, secondary, f, pol_exists) = getmapfile(policy_name)
|
||||
if not f:
|
||||
if pol_exists:
|
||||
err("Cannot find mapfile for policy \'" + policy_name +
|
||||
"\'.\nPlease use makepolicy to create mapping file.")
|
||||
err("Cannot find mapfile for policy \'" + policy_name + "\'.\n")
|
||||
else:
|
||||
err("Unknown policy \'" + policy_name + "\'")
|
||||
|
||||
@@ -608,6 +704,10 @@ def list_labels(policy_name, condition):
|
||||
label = line.split()[3]
|
||||
if label not in labels:
|
||||
labels.append(label)
|
||||
|
||||
if '__NULL_LABEL__' in labels:
|
||||
labels.remove('__NULL_LABEL__')
|
||||
|
||||
return labels
|
||||
|
||||
|
||||
@@ -763,10 +863,10 @@ def res_security_check(resource, domain_label):
|
||||
# provide descriptive error messages
|
||||
if decision == 'DENIED':
|
||||
if label == ssidref2label(NULL_SSIDREF):
|
||||
raise ACMError("Resource '"+resource+"' is not labeled")
|
||||
raise XSMError("Resource '"+resource+"' is not labeled")
|
||||
rtnval = 0
|
||||
else:
|
||||
raise ACMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed")
|
||||
raise XSMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed")
|
||||
rtnval = 0
|
||||
|
||||
# security is off, make sure resource isn't labeled
|
||||
@@ -775,7 +875,7 @@ def res_security_check(resource, domain_label):
|
||||
# xm without ACM are free to use relative paths.
|
||||
(policytype, label, policy) = get_res_label(resource)
|
||||
if policy != 'NULL':
|
||||
raise ACMError("Security is off, but '"+resource+"' is labeled")
|
||||
raise XSMError("Security is off, but '"+resource+"' is labeled")
|
||||
rtnval = 0
|
||||
|
||||
return rtnval
|
||||
@@ -803,10 +903,10 @@ def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
|
||||
# provide descriptive error messages
|
||||
if decision == 'DENIED':
|
||||
if rlabel == ssidref2label(NULL_SSIDREF):
|
||||
#raise ACMError("Resource is not labeled")
|
||||
#raise XSMError("Resource is not labeled")
|
||||
rtnval = 0
|
||||
else:
|
||||
#raise ACMError("Permission denied for resource because label '"+rlabel+"' is not allowed")
|
||||
#raise XSMError("Permission denied for resource because label '"+rlabel+"' is not allowed")
|
||||
rtnval = 0
|
||||
|
||||
# security is off, make sure resource isn't labeled
|
||||
@@ -814,17 +914,35 @@ def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
|
||||
# Note, we can't canonicalise the resource here, because people using
|
||||
# xm without ACM are free to use relative paths.
|
||||
if rpolicy != 'NULL':
|
||||
#raise ACMError("Security is off, but resource is labeled")
|
||||
#raise XSMError("Security is off, but resource is labeled")
|
||||
rtnval = 0
|
||||
|
||||
return rtnval
|
||||
|
||||
|
||||
def validate_label(label, policyref):
|
||||
def validate_label_xapi(xapi_label, dom_or_res):
|
||||
"""
|
||||
Make sure that this label is part of the currently enforced policy
|
||||
and that it references the current policy.
|
||||
dom_or_res defines whether this is a VM ('res') or resource label
|
||||
('res')
|
||||
"""
|
||||
tmp = xapi_label.split(":")
|
||||
if len(tmp) != 3:
|
||||
return -xsconstants.XSERR_BAD_LABEL_FORMAT
|
||||
policytyp, policyref, label = tmp
|
||||
return validate_label(policytyp, policyref, label, dom_or_res)
|
||||
|
||||
|
||||
def validate_label(policytype, policyref, label, dom_or_res):
|
||||
"""
|
||||
Make sure that this label is part of the currently enforced policy
|
||||
and that it reference the current policy.
|
||||
"""
|
||||
if policytype != xsconstants.ACM_POLICY_ID:
|
||||
return -xsconstants.XSERR_WRONG_POLICY_TYPE
|
||||
if not policytype or not label:
|
||||
return -xsconstants.XSERR_BAD_LABEL_FORMAT
|
||||
rc = xsconstants.XSERR_SUCCESS
|
||||
from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
|
||||
curpol = XSPolicyAdminInstance().get_loaded_policy()
|
||||
@@ -832,7 +950,7 @@ def validate_label(label, policyref):
|
||||
rc = -xsconstants.XSERR_BAD_LABEL
|
||||
else:
|
||||
try:
|
||||
label2ssidref(label, curpol.get_name() , 'res')
|
||||
label2ssidref(label, curpol.get_name() , dom_or_res)
|
||||
except:
|
||||
rc = -xsconstants.XSERR_BAD_LABEL
|
||||
return rc
|
||||
@@ -851,11 +969,11 @@ def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
|
||||
olabel = ""
|
||||
if reslabel_xapi == "":
|
||||
return rm_resource_label(resource, oldlabel_xapi)
|
||||
typ, policyref, label = reslabel_xapi.split(":")
|
||||
if typ != xsconstants.ACM_POLICY_ID:
|
||||
return -xsconstants.XSERR_WRONG_POLICY_TYPE
|
||||
if not policyref or not label:
|
||||
return -xsconstants.XSERR_BAD_LABEL_FORMAT
|
||||
|
||||
rc = validate_label_xapi(reslabel_xapi, 'res')
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
return rc
|
||||
|
||||
if oldlabel_xapi not in [ "" ]:
|
||||
tmp = oldlabel_xapi.split(":")
|
||||
if len(tmp) != 3:
|
||||
@@ -866,9 +984,7 @@ def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
|
||||
otyp != xsconstants.INVALID_POLICY_PREFIX + \
|
||||
xsconstants.ACM_POLICY_ID:
|
||||
return -xsconstants.XSERR_WRONG_POLICY_TYPE
|
||||
rc = validate_label(label, policyref)
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
return rc
|
||||
typ, policyref, label = reslabel_xapi.split(":")
|
||||
return set_resource_label(resource, typ, policyref, label, olabel)
|
||||
|
||||
|
||||
@@ -1033,7 +1149,10 @@ def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
|
||||
|
||||
def set_resource_label(resource, policytype, policyref, reslabel, \
|
||||
oreslabel = None):
|
||||
"""Assign a label to a resource
|
||||
"""
|
||||
Xend exports this function via XML-RPC.
|
||||
|
||||
Assign a label to a resource
|
||||
If the old label (oreslabel) is given, then the resource must have
|
||||
that old label.
|
||||
A resource label may be changed if
|
||||
@@ -1046,6 +1165,10 @@ def set_resource_label(resource, policytype, policyref, reslabel, \
|
||||
@rtype: int
|
||||
@return Success (0) or failure value (< 0)
|
||||
"""
|
||||
|
||||
if reslabel != "":
|
||||
ssidref = label2ssidref(reslabel, policyref, 'res')
|
||||
|
||||
try:
|
||||
resource = unify_resname(resource, mustexist=False)
|
||||
except Exception:
|
||||
@@ -1123,7 +1246,10 @@ def format_resource_label(res):
|
||||
return ""
|
||||
|
||||
def get_resource_label(resource):
|
||||
"""Get the assigned resource label of a given resource
|
||||
"""
|
||||
Xend exports this function via XML-RPC.
|
||||
|
||||
Get the assigned resource label of a given resource
|
||||
@param resource: The name of a resource, i.e., "phy:/dev/hda"
|
||||
|
||||
@rtype: list
|
||||
@@ -1161,7 +1287,10 @@ def get_labeled_resources_xapi():
|
||||
|
||||
|
||||
def get_labeled_resources():
|
||||
"""Get a map of all labeled resources
|
||||
"""
|
||||
Xend exports this function via XML-RPC
|
||||
|
||||
Get a map of all labeled resources.
|
||||
@rtype: list
|
||||
@return list of labeled resources
|
||||
"""
|
||||
@@ -1225,6 +1354,7 @@ def change_acm_policy(bin_pol, del_array, chg_array,
|
||||
This function should be called with the lock to the domains
|
||||
held (XendDomain.instance().domains_lock)
|
||||
"""
|
||||
from xen.util.acmpolicy import ACM_LABEL_UNLABELED
|
||||
rc = xsconstants.XSERR_SUCCESS
|
||||
|
||||
domain_label_map = {}
|
||||
@@ -1266,14 +1396,25 @@ def change_acm_policy(bin_pol, del_array, chg_array,
|
||||
continue
|
||||
|
||||
# label been renamed or deleted?
|
||||
if reslabel_map.has_key(label) and cur_policyname == policy:
|
||||
if policytype != xsconstants.ACM_POLICY_ID:
|
||||
continue
|
||||
elif reslabel_map.has_key(label) and cur_policyname == policy:
|
||||
# renaming of an active label; policy may have been renamed
|
||||
label = reslabel_map[label]
|
||||
polname = new_policyname
|
||||
elif label not in polnew_reslabels:
|
||||
# label been removed
|
||||
policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
|
||||
run_resource_label_change_script(key, "", "remove")
|
||||
polname = policy
|
||||
else:
|
||||
# no change to label
|
||||
policytype = xsconstants.ACM_POLICY_ID
|
||||
polname = new_policyname
|
||||
|
||||
# Update entry
|
||||
access_control[key] = \
|
||||
tuple([ policytype, new_policyname, label ])
|
||||
tuple([ policytype, polname, label ])
|
||||
|
||||
# All resources have new labels in the access_control map
|
||||
# There may still be labels in there that are invalid now.
|
||||
@@ -1297,11 +1438,19 @@ def change_acm_policy(bin_pol, del_array, chg_array,
|
||||
|
||||
new_vmlabel = vmlabel
|
||||
if vmlabel_map.has_key(vmlabel):
|
||||
# renaming of the label
|
||||
new_vmlabel = vmlabel_map[vmlabel]
|
||||
if new_vmlabel not in polnew_vmlabels:
|
||||
polname = new_policyname
|
||||
elif new_vmlabel not in polnew_vmlabels and \
|
||||
vmlabel != ACM_LABEL_UNLABELED:
|
||||
# removal of VM label and not the 'unlabeled' label
|
||||
policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
|
||||
polname = policy
|
||||
else:
|
||||
polname = new_policyname
|
||||
|
||||
new_seclab = "%s:%s:%s" % \
|
||||
(policytype, new_policyname, new_vmlabel)
|
||||
(policytype, polname, new_vmlabel)
|
||||
|
||||
domain_label_map[dominfo] = [ sec_lab, new_seclab ]
|
||||
|
||||
@@ -1383,16 +1532,20 @@ def get_security_label(self, xspol=None):
|
||||
return label
|
||||
|
||||
def run_resource_label_change_script(resource, label, command):
|
||||
script = XendOptions.instance().get_resource_label_change_script()
|
||||
if script:
|
||||
parms = {
|
||||
'resource' : resource,
|
||||
'label' : label,
|
||||
'command' : command,
|
||||
}
|
||||
log.info("Running resource label change script %s: %s" %
|
||||
(script, parms))
|
||||
parms.update(os.environ)
|
||||
os.spawnve(os.P_NOWAIT, script[0], script, parms)
|
||||
else:
|
||||
log.info("No script given for relabeling of resources.")
|
||||
def __run_resource_label_change_script(label, command):
|
||||
script = XendOptions.instance().get_resource_label_change_script()
|
||||
if script:
|
||||
parms = {
|
||||
'resource' : resource,
|
||||
'label' : label,
|
||||
'command' : command,
|
||||
}
|
||||
log.info("Running resource label change script %s: %s" %
|
||||
(script, parms))
|
||||
parms.update(os.environ)
|
||||
os.spawnve(os.P_WAIT, script[0], script, parms)
|
||||
else:
|
||||
log.info("No script given for relabeling of resources.")
|
||||
thread = threading.Thread(target=__run_resource_label_change_script,
|
||||
args=(label,command))
|
||||
thread.start()
|
||||
@@ -1,4 +1,6 @@
|
||||
import sys
|
||||
from xen.util import xsconstants
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
class XSMError(Exception):
|
||||
def __init__(self,value):
|
||||
@@ -6,11 +8,27 @@ class XSMError(Exception):
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
|
||||
security_dir_prefix = "";
|
||||
policy_dir_prefix = "";
|
||||
active_policy = "";
|
||||
NULL_SSIDREF = 0;
|
||||
|
||||
#Functions exported through XML-RPC
|
||||
xmlrpc_exports = [
|
||||
'set_resource_label',
|
||||
'get_resource_label',
|
||||
'list_labels',
|
||||
'get_labeled_resources',
|
||||
'set_policy',
|
||||
'get_policy',
|
||||
'activate_policy',
|
||||
'rm_bootpolicy',
|
||||
'get_xstype',
|
||||
'get_domain_label',
|
||||
'set_domain_label'
|
||||
]
|
||||
|
||||
def err(msg):
|
||||
"""Raise XSM-dummy exception.
|
||||
"""
|
||||
@@ -45,7 +63,7 @@ def calc_dom_ssidref_from_info(info):
|
||||
return ""
|
||||
|
||||
def set_security_label(policy, label):
|
||||
return ""
|
||||
return ""
|
||||
|
||||
def ssidref2security_label(ssidref):
|
||||
return ""
|
||||
@@ -55,3 +73,49 @@ def has_authorization(ssidref):
|
||||
|
||||
def get_security_label(self, xspol=None):
|
||||
return ""
|
||||
|
||||
def get_resource_label_xapi(resource):
|
||||
return ""
|
||||
|
||||
def get_labeled_resources_xapi():
|
||||
return {}
|
||||
|
||||
def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
|
||||
err("Command not supported under XSM 'dummy' module.")
|
||||
|
||||
def format_resource_label(res):
|
||||
return ""
|
||||
|
||||
def set_resource_label(resource, policytype, policyref, reslabel,
|
||||
oreslabel = None):
|
||||
err("Command not supported under XSM 'dummy' module.")
|
||||
|
||||
def get_resource_label(resource):
|
||||
return ""
|
||||
|
||||
def list_labels(policy_name, ltype):
|
||||
return []
|
||||
|
||||
def get_labeled_resources():
|
||||
return {}
|
||||
|
||||
def set_policy(xs_type, xml, flags, overwrite):
|
||||
err("Command not supported under xsm 'dummy' module.")
|
||||
|
||||
def get_policy():
|
||||
return "", 0
|
||||
|
||||
def activate_policy():
|
||||
err("Command not supported under xsm 'dummy' module.")
|
||||
|
||||
def rm_bootpolicy():
|
||||
err("Command not supported under xsm 'dummy' module.")
|
||||
|
||||
def get_xstype():
|
||||
return 0
|
||||
|
||||
def get_domain_label(domain):
|
||||
return ""
|
||||
|
||||
def set_domain_label():
|
||||
err("Command not supported under xsm 'dummy' module.")
|
||||
@@ -2,6 +2,9 @@ import sys
|
||||
from xen.lowlevel import flask
|
||||
from xen.xend import sxp
|
||||
|
||||
#Functions exported through XML-RPC
|
||||
xmlrpc_exports = [ ]
|
||||
|
||||
def err(msg):
|
||||
"""Raise XSM-Flask exception.
|
||||
"""
|
||||
|
||||
@@ -647,11 +647,18 @@ class XendConfig(dict):
|
||||
except ValueError, e:
|
||||
raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
|
||||
|
||||
if not 'security' in cfg and sxp.child_value(sxp_cfg, 'security'):
|
||||
cfg['security'] = sxp.child_value(sxp_cfg, 'security')
|
||||
if 'security' in cfg and not cfg.get('security_label'):
|
||||
secinfo = cfg['security']
|
||||
if isinstance(secinfo, list):
|
||||
import xen.util.xsm.xsm as security
|
||||
if security.on():
|
||||
from xen.util.acmpolicy import ACM_LABEL_UNLABELED
|
||||
if not 'security' in cfg and sxp.child_value(sxp_cfg, 'security'):
|
||||
cfg['security'] = sxp.child_value(sxp_cfg, 'security')
|
||||
elif not cfg.get('security_label'):
|
||||
cfg['security'] = [['access_control',
|
||||
['policy', security.get_active_policy_name() ],
|
||||
['label', ACM_LABEL_UNLABELED ]]]
|
||||
|
||||
if 'security' in cfg and not cfg.get('security_label'):
|
||||
secinfo = cfg['security']
|
||||
# The xm command sends a list formatted like this:
|
||||
# [['access_control', ['policy', 'xm-test'],['label', 'red']],
|
||||
# ['ssidref', 196611]]
|
||||
@@ -664,12 +671,16 @@ class XendConfig(dict):
|
||||
policy = secinfo[idx][aidx][1]
|
||||
if secinfo[idx][aidx][0] == "label":
|
||||
label = secinfo[idx][aidx][1]
|
||||
import xen.util.xsm.xsm as security
|
||||
cfg['security_label'] = \
|
||||
security.set_security_label(policy, label)
|
||||
if not sxp.child_value(sxp_cfg, 'security_label'):
|
||||
del cfg['security']
|
||||
|
||||
sec_lab = cfg['security_label'].split(":")
|
||||
if len(sec_lab) != 3:
|
||||
raise XendConfigError("Badly formatted security label: %s"
|
||||
% cfg['security_label'])
|
||||
|
||||
old_state = sxp.child_value(sxp_cfg, 'state')
|
||||
if old_state:
|
||||
for i in range(len(CONFIG_OLD_DOM_STATES)):
|
||||
|
||||
@@ -2460,12 +2460,14 @@ class XendDomainInfo:
|
||||
self, label):
|
||||
return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
|
||||
|
||||
#Check label against expected one.
|
||||
old_label = self.get_security_label(xspol_old)
|
||||
if old_label != old_seclab:
|
||||
log.info("old_label != old_seclab: %s != %s" %
|
||||
(old_label, old_seclab))
|
||||
return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
|
||||
#Check label against expected one. Can only do this
|
||||
# if the policy hasn't changed underneath in the meantime
|
||||
if xspol_old == None:
|
||||
old_label = self.get_security_label()
|
||||
if old_label != old_seclab:
|
||||
log.info("old_label != old_seclab: %s != %s" %
|
||||
(old_label, old_seclab))
|
||||
return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
|
||||
|
||||
# relabel domain in the hypervisor
|
||||
rc, errors = security.relabel_domains([[domid, new_ssidref]])
|
||||
@@ -2477,6 +2479,7 @@ class XendDomainInfo:
|
||||
# HALTED, RUNNING or PAUSED
|
||||
if domid == 0:
|
||||
if xspol:
|
||||
self.info['security_label'] = seclab
|
||||
ssidref = poladmin.set_domain0_bootlabel(xspol, label)
|
||||
else:
|
||||
return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
|
||||
@@ -2488,6 +2491,7 @@ class XendDomainInfo:
|
||||
return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
|
||||
|
||||
self.info['security_label'] = seclab
|
||||
|
||||
try:
|
||||
xen.xend.XendDomain.instance().managed_config_save(self)
|
||||
except:
|
||||
|
||||
@@ -99,9 +99,10 @@ class XSPolicyAdmin:
|
||||
# This is meant as an update to a currently loaded policy
|
||||
if flags & xsconstants.XS_INST_LOAD == 0:
|
||||
raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
|
||||
if flags & xsconstants.XS_INST_BOOT == 0:
|
||||
self.rm_bootpolicy()
|
||||
rc, errors = loadedpol.update(xmltext)
|
||||
if rc == 0:
|
||||
self.rm_bootpolicy()
|
||||
irc = self.activate_xspolicy(loadedpol, flags)
|
||||
# policy is loaded; if setting the boot flag fails it's ok.
|
||||
return (loadedpol, rc, errors)
|
||||
@@ -279,8 +280,7 @@ class XSPolicyAdmin:
|
||||
return None
|
||||
|
||||
def get_hv_loaded_policy_name(self):
|
||||
security.refresh_security_policy()
|
||||
return security.active_policy
|
||||
return security.get_active_policy_name()
|
||||
|
||||
def get_policy_by_name(self, name):
|
||||
for pol in self.xsobjs.values():
|
||||
@@ -300,8 +300,10 @@ class XSPolicyAdmin:
|
||||
return title
|
||||
|
||||
def set_domain0_bootlabel(self, xspol, label):
|
||||
""" Set the domain-0 bootlabel under the given policy """
|
||||
return xspol.set_vm_bootlabel(label)
|
||||
""" Set the domain-0 bootlabel under the given policy. If the
|
||||
current policy is the default policy, it will remove it. """
|
||||
rm_entry = (xspol.get_name() == "DEFAULT")
|
||||
return xspol.set_vm_bootlabel(label, rm_entry)
|
||||
|
||||
def rm_domain0_bootlabel(self):
|
||||
""" Remove the domain-0 bootlabel from the default boot title """
|
||||
|
||||
@@ -207,6 +207,12 @@ class XMLRPCServer:
|
||||
self.server.register_function(domain_create, 'xend.domain.create')
|
||||
self.server.register_function(domain_restore, 'xend.domain.restore')
|
||||
|
||||
# A couple of the security functions
|
||||
from xen.util.xsm import xsm as security
|
||||
for name in security.xmlrpc_exports:
|
||||
fn = getattr(security, name)
|
||||
self.server.register_function(fn, "xend.security.%s" % name)
|
||||
|
||||
self.server.register_introspection_functions()
|
||||
self.ready = True
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2007 International Business Machines Corp.
|
||||
# Author: Stefan Berger <stefanb@us.ibm.com>
|
||||
#============================================================================
|
||||
|
||||
"""Activate the managed policy of the system.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from xen.util import xsconstants
|
||||
from xml.dom import minidom
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import getpolicy, setpolicy
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.main import server
|
||||
|
||||
def help():
|
||||
return """
|
||||
Usage: xm activatepolicy [options]
|
||||
|
||||
Activate the xend-managed policy.
|
||||
|
||||
The following options are defined:
|
||||
--load Load the policy into the hypervisor.
|
||||
--boot Have the system boot with the policy. Changes the default
|
||||
title in grub.conf.
|
||||
--noboot Remove the policy from the default entry in grub.conf.
|
||||
--remove Attempt to remove the current policy by installing the
|
||||
default policy; this works only if no domains are
|
||||
running.
|
||||
"""
|
||||
|
||||
def activate_policy(flags):
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
xs_ref = policystate['xs_ref']
|
||||
if int(policystate['type']) == 0 or xs_ref == "":
|
||||
print "No policy is installed."
|
||||
return
|
||||
rc = int(server.xenapi.XSPolicy.activate_xspolicy(xs_ref, flags))
|
||||
if rc == flags:
|
||||
print "Successfully activated the policy."
|
||||
else:
|
||||
print "An error occurred trying to activate the policy: %s" % \
|
||||
xsconstants.xserr2string(rc)
|
||||
|
||||
def remove_bootpolicy():
|
||||
server.xenapi.XSPolicy.rm_xsbootpolicy()
|
||||
|
||||
def install_default_policy():
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('xm needs to be configured to use the xen-api.')
|
||||
xs_type = int(server.xenapi.XSPolicy.get_xstype())
|
||||
if xs_type & xsconstants.XS_POLICY_ACM == 0:
|
||||
raise OptionError('ACM policy type not supported on system.')
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
print 'No policy is installed.'
|
||||
return
|
||||
if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
|
||||
print "Unknown policy type '%s'." % policystate['type']
|
||||
flags = int(policystate['flags'])
|
||||
if flags & xsconstants.XS_INST_LOAD == 0:
|
||||
print "Default policy is already loaded."
|
||||
return
|
||||
setpolicy.setpolicy(xsconstants.ACM_POLICY_ID, 'default', flags, True,
|
||||
False)
|
||||
|
||||
def main(argv):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('xm needs to be configured to use the xen-api.')
|
||||
flags = 0
|
||||
c = 1
|
||||
|
||||
while c < len(argv):
|
||||
if '--boot' == argv[c]:
|
||||
flags |= xsconstants.XS_INST_BOOT
|
||||
elif '--load' == argv[c]:
|
||||
flags |= xsconstants.XS_INST_LOAD
|
||||
elif '--noboot' == argv[c]:
|
||||
remove_bootpolicy()
|
||||
elif '--remove' == argv[c]:
|
||||
install_default_policy()
|
||||
return
|
||||
else:
|
||||
raise OptionError("Unknown command line option '%s'" % argv[c])
|
||||
c += 1
|
||||
|
||||
if flags != 0:
|
||||
activate_policy(flags)
|
||||
|
||||
getpolicy.getpolicy(False)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(sys.argv)
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: %s\n' % str(e))
|
||||
sys.exit(-1)
|
||||
@@ -22,7 +22,6 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from xen.util import dictio
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.util import xsconstants
|
||||
@@ -37,14 +36,12 @@ def help():
|
||||
xm addlabel <label> vif-<idx> <domain name> [<policy type>:<policy>]
|
||||
|
||||
This program adds an acm_label entry into the 'configfile'
|
||||
for a domain or allows to label a xend-managed domain.
|
||||
The global resource label file for is extended with labels for
|
||||
resources. It derives the policy from the running hypervisor
|
||||
if it is not given (optional parameter). If a label already
|
||||
exists for the given domain or resource, then addlabel fails.
|
||||
for a domain, allows to label a xend-managed domain, resources
|
||||
of the VIF of a mangaged domain (requires xm to be used in
|
||||
Xen-API mode).
|
||||
|
||||
For xend-managed domains, the 'mgt' parameter should be used and
|
||||
the 'xm' tool must have been configured to use the xen-api for
|
||||
the 'xm' tool must have been configured to use the xen-npi for
|
||||
communication with xen. If a policy is provided as last parameter,
|
||||
its type must also be given. Currently only one type of policy is
|
||||
supported and identified as 'ACM'. An example for a valid string
|
||||
@@ -84,29 +81,22 @@ def add_resource_label(label, resource, policyref, policy_type):
|
||||
"""
|
||||
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
|
||||
# sanity check: make sure this label can be instantiated later on
|
||||
ssidref = security.label2ssidref(label, policyref, 'res')
|
||||
|
||||
#build canonical resource name
|
||||
resource = security.unify_resname(resource,mustexist=False)
|
||||
|
||||
# see if this resource is already in the file
|
||||
access_control = {}
|
||||
fil = security.res_label_filename
|
||||
try:
|
||||
access_control = dictio.dict_read("resources", fil)
|
||||
except:
|
||||
print "Resource file not found, creating new file at:"
|
||||
print "%s" % (fil)
|
||||
|
||||
if access_control.has_key(resource):
|
||||
security.err("This resource is already labeled.")
|
||||
|
||||
# write the data to file
|
||||
new_entry = { resource : tuple([policy_type, policyref, label]) }
|
||||
access_control.update(new_entry)
|
||||
dictio.dict_write(access_control, "resources", fil)
|
||||
old = server.xend.security.get_resource_label(resource)
|
||||
if len(old) == 0:
|
||||
try:
|
||||
rc = server.xend.security.set_resource_label(resource,
|
||||
policy_type,
|
||||
policyref,
|
||||
label)
|
||||
except Exception, e:
|
||||
raise
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
security.err("An error occurred labeling the resource: %s" % \
|
||||
xsconstants.xserr2string(-rc))
|
||||
else:
|
||||
old = security.format_resource_label(old)
|
||||
security.err("'%s' is already labeled with '%s'." % \
|
||||
(resource,old))
|
||||
else:
|
||||
res = [ policy_type, policyref, label ]
|
||||
res_xapi = security.format_resource_label(res)
|
||||
@@ -141,30 +131,48 @@ def add_domain_label(label, configfile, policyref):
|
||||
config_fd.close()
|
||||
|
||||
def add_domain_label_xapi(label, domainname, policyref, policy_type):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('Xm must be configured to use the xen-api.')
|
||||
uuids = server.xenapi.VM.get_by_name_label(domainname)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('There are multiple domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
|
||||
try:
|
||||
old_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
|
||||
except Exception, e:
|
||||
raise security.XSMError("Could not label the domain: %s" % e)
|
||||
if int(rc) < 0:
|
||||
raise OptionError('Could not label domain.')
|
||||
else:
|
||||
ssidref = int(rc)
|
||||
if ssidref != 0:
|
||||
print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %\
|
||||
(domainname,label,ssidref)
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
old_seclab = server.xend.security.get_domain_label(domainname)
|
||||
if old_seclab[0] == '\'':
|
||||
old_seclab = old_seclab[1:]
|
||||
results = server.xend.security.set_domain_label(domainname,
|
||||
sec_lab,
|
||||
old_seclab)
|
||||
rc, ssidref = results
|
||||
if rc == xsconstants.XSERR_SUCCESS:
|
||||
if ssidref != 0:
|
||||
print "Successfully set the label of domain '%s' to '%s'.\n" \
|
||||
% (domainname,label)
|
||||
else:
|
||||
print "Successfully set the label of the dormant domain " \
|
||||
"'%s' to '%s'." % (domainname,label)
|
||||
else:
|
||||
print "Set the label of dormant domain '%s' to '%s'." % \
|
||||
(domainname,label)
|
||||
msg = xsconstants.xserr2string(-rc)
|
||||
raise security.XSMError("An error occurred relabeling "
|
||||
"the domain: %s" % msg)
|
||||
else:
|
||||
uuids = server.xenapi.VM.get_by_name_label(domainname)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('There are multiple domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
try:
|
||||
old_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
|
||||
except Exception, e:
|
||||
raise security.XSMError("Could not label the domain: %s" % e)
|
||||
if int(rc) < 0:
|
||||
raise OptionError('Could not label domain.')
|
||||
else:
|
||||
ssidref = int(rc)
|
||||
if ssidref != 0:
|
||||
print "Successfully set the label of domain '%s' to '%s'.\n" \
|
||||
% (domainname,label)
|
||||
else:
|
||||
print "Successfully set the label of the dormant domain " \
|
||||
"'%s' to '%s'." % (domainname,label)
|
||||
|
||||
def add_vif_label(label, vmname, idx, policyref, policy_type):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
@@ -212,7 +220,7 @@ def main(argv):
|
||||
if argv[2].lower() == "dom":
|
||||
configfile = argv[3]
|
||||
if configfile[0] != '/':
|
||||
for prefix in [".", "/etc/xen"]:
|
||||
for prefix in [os.path.realpath(os.path.curdir), "/etc/xen"]:
|
||||
configfile = prefix + "/" + configfile
|
||||
if os.path.isfile(configfile):
|
||||
break
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2006 International Business Machines Corp.
|
||||
# Author: Reiner Sailer <sailer@us.ibm.com>
|
||||
# Contributions: Stefan Berger <stefanb@us.ibm.com>
|
||||
#============================================================================
|
||||
"""Configuring a security policy into the boot configuration
|
||||
"""
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
import tempfile
|
||||
import os, stat
|
||||
import shutil
|
||||
import string
|
||||
import re
|
||||
from xen.util.xsm.xsm import err
|
||||
from xen.util.xsm.xsm import policy_dir_prefix, xen_title_re
|
||||
from xen.util.xsm.xsm import boot_filename, altboot_filename
|
||||
from xen.util.xsm.xsm import any_title_re, xen_kernel_re, any_module_re
|
||||
from xen.util.xsm.xsm import empty_line_re, binary_name_re, policy_name_re
|
||||
from xen.util import xsconstants
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.main import server
|
||||
from xen.util.acmpolicy import ACMPolicy
|
||||
|
||||
def help():
|
||||
return """
|
||||
Adds a 'module' line to the Xen grub configuration file entry
|
||||
so that Xen boots with a specific access control policy. If
|
||||
boot-title is not given, then this script tries to determine
|
||||
it by looking for a title starting with \"XEN\". If there are
|
||||
multiple entries matching, then it must be called with the unique
|
||||
beginning of the title's name.\n"""
|
||||
|
||||
def strip_title(line):
|
||||
"""
|
||||
strips whitespace left and right and cuts 'title'
|
||||
"""
|
||||
s_title = string.strip(line)
|
||||
pos = string.index(s_title, "title")
|
||||
if pos >= 0:
|
||||
return s_title[pos+6:]
|
||||
else:
|
||||
return s_title
|
||||
|
||||
|
||||
def insert_policy(boot_file, alt_boot_file, user_title, policy_name):
|
||||
"""
|
||||
inserts policy binary file as last line of the grub entry
|
||||
matching the user_title or default title
|
||||
"""
|
||||
if user_title:
|
||||
#replace "(" by "\(" and ")" by "\)" for matching
|
||||
user_title = string.replace(user_title, "(", "\(")
|
||||
user_title = string.replace(user_title, ")", "\)")
|
||||
user_title_re = re.compile("\s*title\s+.*%s" \
|
||||
% user_title, re.IGNORECASE)
|
||||
else:
|
||||
user_title_re = xen_title_re
|
||||
|
||||
within_xen_title = 0
|
||||
within_xen_entry = 0
|
||||
insert_at_end_of_entry = 0
|
||||
path_prefix = ''
|
||||
this_title = ''
|
||||
extended_titles = []
|
||||
(tmp_fd, tmp_grub) = tempfile.mkstemp()
|
||||
#First check whether menu.lst exists
|
||||
if not os.path.isfile(boot_file):
|
||||
#take alternate boot file (grub.conf) instead
|
||||
boot_file = alt_boot_file
|
||||
#follow symlink since menue.lst might be linked to grub.conf
|
||||
if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
|
||||
new_name = os.readlink(boot_file)
|
||||
if new_name[0] == "/":
|
||||
boot_file = new_name
|
||||
else:
|
||||
path = boot_file.split('/')
|
||||
path[len(path)-1] = new_name
|
||||
boot_file = '/'.join(path)
|
||||
if not os.path.exists(boot_file):
|
||||
err("Boot file \'%s\' not found." % boot_file)
|
||||
grub_fd = open(boot_file)
|
||||
for line in grub_fd:
|
||||
if user_title_re.match(line):
|
||||
this_title = strip_title(line)
|
||||
within_xen_title = 1
|
||||
elif within_xen_title and xen_kernel_re.match(line):
|
||||
insert_at_end_of_entry = 1
|
||||
#use prefix from xen.gz path for policy
|
||||
path_prefix = line.split()[1]
|
||||
idx = path_prefix.rfind('/')
|
||||
if idx >= 0:
|
||||
path_prefix = path_prefix[0:idx+1]
|
||||
else:
|
||||
path_prefix = ''
|
||||
elif any_module_re.match(line) and insert_at_end_of_entry:
|
||||
if binary_name_re.match(line):
|
||||
#delete existing policy module line
|
||||
line=''
|
||||
elif any_title_re.match(line):
|
||||
within_xen_title = 0
|
||||
|
||||
if (empty_line_re.match(line) or any_title_re.match(line)) and \
|
||||
insert_at_end_of_entry:
|
||||
#newline or new title: we insert the policy module line here
|
||||
os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
|
||||
extended_titles.append(this_title)
|
||||
insert_at_end_of_entry = 0
|
||||
#write the line that was read (except potential existing policy entry)
|
||||
os.write(tmp_fd, line)
|
||||
|
||||
if insert_at_end_of_entry:
|
||||
#last entry, no empty line at end of file
|
||||
os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
|
||||
extended_titles.append(this_title)
|
||||
|
||||
#if more than one entry was changed, abort
|
||||
if len(extended_titles) > 1:
|
||||
err("Following boot entries matched: %s. \nPlease specify "
|
||||
"unique part of the boot title." % extended_titles)
|
||||
if len(extended_titles) == 0:
|
||||
err("Boot entry not found. Please specify unique part "
|
||||
"of the boot title.")
|
||||
|
||||
#temp file might be destroyed when closing it, first copy it
|
||||
shutil.move(boot_file, boot_file+"_save")
|
||||
shutil.copyfile(tmp_grub, boot_file)
|
||||
os.close(tmp_fd)
|
||||
#sometimes the temp file does not disappear
|
||||
try:
|
||||
os.remove(tmp_grub)
|
||||
except:
|
||||
pass
|
||||
return extended_titles[0]
|
||||
|
||||
def cfgbootpolicy_xapi(policy, user_title=None):
|
||||
xstype = int(server.xenapi.XSPolicy.get_xstype())
|
||||
if xstype & xsconstants.XS_POLICY_ACM == 0:
|
||||
raise OptionError("ACM policy not supported on system.")
|
||||
if user_title:
|
||||
raise OptionError("Only the default title is supported with Xen-API.")
|
||||
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
print "No policy is installed."
|
||||
return
|
||||
|
||||
if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
|
||||
print "Unknown policy type '%s'." % policystate['type']
|
||||
return
|
||||
else:
|
||||
xml = policystate['repr']
|
||||
xs_ref = policystate['xs_ref']
|
||||
if not xml:
|
||||
OptionError("No policy installed on system?")
|
||||
acmpol = ACMPolicy(xml=xml)
|
||||
if acmpol.get_name() != policy:
|
||||
raise OptionError("Policy installed on system '%s' does not "
|
||||
"match the requested policy '%s'" %
|
||||
(acmpol.get_name(), policy))
|
||||
flags = int(policystate['flags']) | xsconstants.XS_INST_BOOT
|
||||
rc = int(server.xenapi.XSPolicy.activate_xspolicy(xs_ref, flags))
|
||||
if rc == flags:
|
||||
print "Successfully enabled the policy for having the system" \
|
||||
" booted with."
|
||||
else:
|
||||
print "An error occurred during the operation: %s" % \
|
||||
xsconstants.xserr2string(rc)
|
||||
|
||||
|
||||
def main(argv):
|
||||
user_kver = None
|
||||
user_title = None
|
||||
if len(argv) == 2:
|
||||
policy = argv[1]
|
||||
elif len(argv) == 3:
|
||||
policy = argv[1]
|
||||
user_title = argv[2]
|
||||
else:
|
||||
raise OptionError('Invalid number of arguments')
|
||||
|
||||
if not policy_name_re.match(policy):
|
||||
raise OptionError("Illegal policy name: '%s'" % policy)
|
||||
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
cfgbootpolicy_xapi(policy)
|
||||
else:
|
||||
policy_file = '/'.join([policy_dir_prefix] + policy.split('.'))
|
||||
src_binary_policy_file = policy_file + ".bin"
|
||||
#check if .bin exists or if policy file exists
|
||||
if not os.path.isfile(src_binary_policy_file):
|
||||
if not os.path.isfile(policy_file + "-security_policy.xml"):
|
||||
raise OptionError("Unknown policy '%s'" % policy)
|
||||
else:
|
||||
err_msg = "Cannot find binary file for policy '%s'." % policy
|
||||
err_msg += " Please use makepolicy to create binary file."
|
||||
raise OptionError(err_msg)
|
||||
|
||||
dst_binary_policy_file = "/boot/" + policy + ".bin"
|
||||
shutil.copyfile(src_binary_policy_file, dst_binary_policy_file)
|
||||
|
||||
entryname = insert_policy(boot_filename, altboot_filename,
|
||||
user_title, policy)
|
||||
print "Boot entry '%s' extended and \'%s\' copied to /boot" \
|
||||
% (entryname, policy + ".bin")
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(sys.argv)
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: ' + str(e) + '\n')
|
||||
sys.exit(-1)
|
||||
@@ -659,11 +659,7 @@ def configure_security(config, vals):
|
||||
['policy', policy],
|
||||
['label', label] ]
|
||||
|
||||
#calculate ssidref from label
|
||||
ssidref = security.label2ssidref(label, policy, 'dom')
|
||||
if not ssidref :
|
||||
err("ERROR calculating ssidref from access_control.")
|
||||
security_label = ['security', [ config_access_control, ['ssidref' , ssidref ] ] ]
|
||||
security_label = ['security', [ config_access_control ] ]
|
||||
config.append(security_label)
|
||||
elif num > 1:
|
||||
err("VM config error: Multiple access_control definitions!")
|
||||
@@ -1151,121 +1147,6 @@ def parseCommandLine(argv):
|
||||
|
||||
return (gopts, config)
|
||||
|
||||
|
||||
def check_domain_label(config, verbose):
|
||||
"""All that we need to check here is that the domain label exists and
|
||||
is not null when security is on. Other error conditions are
|
||||
handled when the config file is parsed.
|
||||
"""
|
||||
answer = 0
|
||||
default_label = None
|
||||
secon = 0
|
||||
if security.on():
|
||||
default_label = security.ssidref2label(security.NULL_SSIDREF)
|
||||
secon = 1
|
||||
|
||||
# get the domain acm_label
|
||||
dom_label = None
|
||||
dom_name = None
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'security':
|
||||
dom_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
|
||||
if sxp.name(x) == 'name':
|
||||
dom_name = sxp.child0(x)
|
||||
|
||||
# sanity check on domain label
|
||||
if verbose:
|
||||
print "Checking domain:"
|
||||
if (not secon) and (not dom_label):
|
||||
answer = 1
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (dom_name)
|
||||
elif (secon) and (dom_label) and (dom_label != default_label):
|
||||
answer = 1
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (dom_name)
|
||||
else:
|
||||
print " %s: DENIED" % (dom_name)
|
||||
if not secon:
|
||||
print " --> Security off, but domain labeled"
|
||||
else:
|
||||
print " --> Domain not labeled"
|
||||
answer = 0
|
||||
|
||||
return answer
|
||||
|
||||
def config_security_check(config, verbose):
|
||||
"""Checks each resource listed in the config to see if the active
|
||||
policy will permit creation of a new domain using the config.
|
||||
Returns 1 if the config passes all tests, otherwise 0.
|
||||
"""
|
||||
answer = 1
|
||||
|
||||
# get the domain acm_label
|
||||
domain_label = None
|
||||
domain_policy = None
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'security':
|
||||
domain_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
|
||||
domain_policy = sxp.child_value(sxp.name(sxp.child0(x)), 'policy')
|
||||
|
||||
# if no domain label, use default
|
||||
if not domain_label and security.on():
|
||||
try:
|
||||
domain_label = security.ssidref2label(security.NULL_SSIDREF)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc(limit=1)
|
||||
return 0
|
||||
domain_policy = 'NULL'
|
||||
elif not domain_label:
|
||||
domain_label = ""
|
||||
domain_policy = 'NULL'
|
||||
|
||||
if verbose:
|
||||
print "Checking resources:"
|
||||
|
||||
# build a list of all resources in the config file
|
||||
resources = []
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'device':
|
||||
if sxp.name(sxp.child0(x)) == 'vbd':
|
||||
resources.append(sxp.child_value(sxp.child0(x), 'uname'))
|
||||
|
||||
# perform a security check on each resource
|
||||
for resource in resources:
|
||||
try:
|
||||
security.res_security_check(resource, domain_label)
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (resource)
|
||||
|
||||
except security.ACMError:
|
||||
print " %s: DENIED" % (resource)
|
||||
(poltype, res_label, res_policy) = security.get_res_label(resource)
|
||||
if not res_label:
|
||||
res_label = ""
|
||||
print " --> res: %s (%s:%s)" % (str(res_label),
|
||||
str(poltype), str(res_policy))
|
||||
print " --> dom: %s (%s:%s)" % (str(domain_label),
|
||||
str(poltype), str(domain_policy))
|
||||
|
||||
answer = 0
|
||||
|
||||
return answer
|
||||
|
||||
def create_security_check(config):
|
||||
passed = 0
|
||||
try:
|
||||
if check_domain_label(config, verbose=0):
|
||||
if config_security_check(config, verbose=0):
|
||||
passed = 1
|
||||
else:
|
||||
print "Checking resources: (skipped)"
|
||||
except security.XSMError:
|
||||
sys.exit(-1)
|
||||
|
||||
return passed
|
||||
|
||||
def help():
|
||||
return str(gopts)
|
||||
|
||||
@@ -1317,9 +1198,6 @@ def main(argv):
|
||||
|
||||
map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
|
||||
elif not opts.is_xml:
|
||||
if not create_security_check(config):
|
||||
raise security.XSMError(
|
||||
'Security Configuration prevents domain from starting')
|
||||
dom = make_domain(opts, config)
|
||||
|
||||
def do_console(domain_name):
|
||||
|
||||
@@ -31,14 +31,117 @@ def help():
|
||||
the resources. The status of each resource is listed
|
||||
individually along with the final security decision."""
|
||||
|
||||
|
||||
def check_domain_label(config, verbose):
|
||||
"""All that we need to check here is that the domain label exists and
|
||||
is not null when security is on. Other error conditions are
|
||||
handled when the config file is parsed.
|
||||
"""
|
||||
answer = 0
|
||||
default_label = None
|
||||
secon = 0
|
||||
if security.on():
|
||||
default_label = security.ssidref2label(security.NULL_SSIDREF)
|
||||
secon = 1
|
||||
|
||||
# get the domain acm_label
|
||||
dom_label = None
|
||||
dom_name = None
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'security':
|
||||
dom_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
|
||||
if sxp.name(x) == 'name':
|
||||
dom_name = sxp.child0(x)
|
||||
|
||||
# sanity check on domain label
|
||||
if verbose:
|
||||
print "Checking domain:"
|
||||
if (not secon) and (not dom_label):
|
||||
answer = 1
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (dom_name)
|
||||
elif (secon) and (dom_label) and (dom_label != default_label):
|
||||
answer = 1
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (dom_name)
|
||||
else:
|
||||
print " %s: DENIED" % (dom_name)
|
||||
if not secon:
|
||||
print " --> Security off, but domain labeled"
|
||||
else:
|
||||
print " --> Domain not labeled"
|
||||
answer = 0
|
||||
|
||||
return answer
|
||||
|
||||
def config_security_check(config, verbose):
|
||||
"""Checks each resource listed in the config to see if the active
|
||||
policy will permit creation of a new domain using the config.
|
||||
Returns 1 if the config passes all tests, otherwise 0.
|
||||
"""
|
||||
answer = 1
|
||||
|
||||
# get the domain acm_label
|
||||
domain_label = None
|
||||
domain_policy = None
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'security':
|
||||
domain_label = sxp.child_value(sxp.name(sxp.child0(x)), 'label')
|
||||
domain_policy = sxp.child_value(sxp.name(sxp.child0(x)), 'policy')
|
||||
|
||||
# if no domain label, use default
|
||||
if not domain_label and security.on():
|
||||
try:
|
||||
domain_label = security.ssidref2label(security.NULL_SSIDREF)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc(limit=1)
|
||||
return 0
|
||||
domain_policy = 'NULL'
|
||||
elif not domain_label:
|
||||
domain_label = ""
|
||||
domain_policy = 'NULL'
|
||||
|
||||
if verbose:
|
||||
print "Checking resources:"
|
||||
|
||||
# build a list of all resources in the config file
|
||||
resources = []
|
||||
for x in sxp.children(config):
|
||||
if sxp.name(x) == 'device':
|
||||
if sxp.name(sxp.child0(x)) == 'vbd':
|
||||
resources.append(sxp.child_value(sxp.child0(x), 'uname'))
|
||||
|
||||
# perform a security check on each resource
|
||||
for resource in resources:
|
||||
try:
|
||||
security.res_security_check(resource, domain_label)
|
||||
if verbose:
|
||||
print " %s: PERMITTED" % (resource)
|
||||
|
||||
except security.XSMError:
|
||||
print " %s: DENIED" % (resource)
|
||||
(poltype, res_label, res_policy) = security.get_res_label(resource)
|
||||
if not res_label:
|
||||
res_label = ""
|
||||
print " --> res: %s (%s:%s)" % (str(res_label),
|
||||
str(poltype), str(res_policy))
|
||||
print " --> dom: %s (%s:%s)" % (str(domain_label),
|
||||
str(poltype), str(domain_policy))
|
||||
|
||||
answer = 0
|
||||
|
||||
return answer
|
||||
|
||||
|
||||
def main (argv):
|
||||
if len(argv) != 2:
|
||||
raise OptionError('Invalid number of arguments')
|
||||
|
||||
passed = 0
|
||||
(opts, config) = create.parseCommandLine(argv)
|
||||
if create.check_domain_label(config, verbose=1):
|
||||
if create.config_security_check(config, verbose=1):
|
||||
if check_domain_label(config, verbose=1):
|
||||
if config_security_check(config, verbose=1):
|
||||
passed = 1
|
||||
else:
|
||||
print "Checking resources: (skipped)"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"""Show the label for a domain or resoruce.
|
||||
"""
|
||||
import sys, os, re
|
||||
from xen.util import dictio
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util import xsconstants
|
||||
from xen.xm.opts import OptionError
|
||||
@@ -33,36 +32,25 @@ def help():
|
||||
xm getlabel res <resource>
|
||||
xm getlabel vif-<idx> <vmname>
|
||||
|
||||
This program shows the label for a domain, resource or virtual network
|
||||
interface of a Xend-managed domain."""
|
||||
This program shows the label for a domain from its configuration
|
||||
file, the label of a Xend-managed domain, that of a resources or
|
||||
the label of a virtual network interface of a managed domain
|
||||
(requires xm to be used in Xen-API mode).
|
||||
"""
|
||||
|
||||
def get_resource_label(resource):
|
||||
"""Gets the resource label
|
||||
"""
|
||||
#build canonical resource name
|
||||
resource = security.unify_resname(resource)
|
||||
|
||||
# read in the resource file
|
||||
fil = security.res_label_filename
|
||||
try:
|
||||
access_control = dictio.dict_read("resources", fil)
|
||||
except:
|
||||
raise OptionError("Resource label file not found")
|
||||
|
||||
# get the entry and print label
|
||||
if access_control.has_key(resource):
|
||||
tmp = access_control[resource]
|
||||
if len(tmp) == 2:
|
||||
policy, label = tmp
|
||||
policytype = xsconstants.ACM_POLICY_ID
|
||||
elif len(tmp) == 3:
|
||||
policytype, policy, label = tmp
|
||||
else:
|
||||
raise security.ACMError("Resource not properly labeled. "
|
||||
"Please relabel the resource.")
|
||||
print policytype+":"+policy+":"+label
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
reslabel = server.xenapi.XSPolicy.get_resource_label(resource)
|
||||
if reslabel == "":
|
||||
raise security.XSMError("Resource not labeled")
|
||||
print reslabel
|
||||
else:
|
||||
raise security.XSMError("Resource not labeled")
|
||||
reslabel = server.xend.security.get_resource_label(resource)
|
||||
if len(reslabel) == 0:
|
||||
raise security.XSMError("Resource not labeled")
|
||||
print ":".join(reslabel)
|
||||
|
||||
|
||||
def get_domain_label(configfile):
|
||||
@@ -120,16 +108,19 @@ def get_vif_label(vmname, idx):
|
||||
sec_lab = server.xenapi.VIF.get_security_label(vif_ref)
|
||||
print "%s" % sec_lab
|
||||
|
||||
def get_domain_label_xapi(domainname):
|
||||
def get_domain_label_xapi(domain):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('xm needs to be configure to use the xen-api.')
|
||||
uuids = server.xenapi.VM.get_by_name_label(domainname)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('There are multiple domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
sec_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
sec_lab = server.xend.security.get_domain_label(domain)
|
||||
if len(sec_lab) > 0 and sec_lab[0] == '\'':
|
||||
sec_lab = sec_lab[1:]
|
||||
else:
|
||||
uuids = server.xenapi.VM.get_by_name_label(domain)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('There are multiple domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
sec_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
print "%s" %sec_lab
|
||||
|
||||
def main(argv):
|
||||
@@ -164,4 +155,3 @@ if __name__ == '__main__':
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: %s\n' % str(e))
|
||||
sys.exit(-1)
|
||||
|
||||
@@ -36,47 +36,88 @@ def help():
|
||||
|
||||
Get the policy managed by xend."""
|
||||
|
||||
def getpolicy(dumpxml):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('xm needs to be configured to use the xen-api.')
|
||||
|
||||
def display_policy_info(acmpol, policytype, uuid, version, flags,
|
||||
dumpxml, xml):
|
||||
print "Policy name : %s" % acmpol.get_name()
|
||||
print "Policy type : %s" % policytype
|
||||
if uuid:
|
||||
print "Reference : %s" % uuid
|
||||
print "Version of XML policy : %s" % version
|
||||
|
||||
state = []
|
||||
if flags & xsconstants.XS_INST_LOAD:
|
||||
state.append("loaded")
|
||||
if flags & xsconstants.XS_INST_BOOT:
|
||||
state.append("activated for boot")
|
||||
print "Policy configuration : %s" % ", ".join(state)
|
||||
if dumpxml:
|
||||
if xml:
|
||||
dom = minidom.parseString(xml.encode("utf-8"))
|
||||
print "%s" % dom.toprettyxml(indent=" ",newl="\n")
|
||||
|
||||
|
||||
def display_security_subsystems(xstype):
|
||||
types = []
|
||||
xstype = int(server.xenapi.XSPolicy.get_xstype())
|
||||
if xstype & xsconstants.XS_POLICY_ACM:
|
||||
types.append("ACM")
|
||||
xstype ^= xsconstants.XS_POLICY_ACM
|
||||
if xstype != 0:
|
||||
types.append("unsupported (%08x)" % xstype)
|
||||
if len(types) == 0:
|
||||
types.append("None")
|
||||
print "Supported security subsystems : %s \n" % ", ".join(types)
|
||||
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
print "No policy is installed."
|
||||
return
|
||||
if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
|
||||
print "Unknown policy type '%s'." % policystate['type']
|
||||
else:
|
||||
xml = policystate['repr']
|
||||
acmpol = None
|
||||
if xml:
|
||||
acmpol = ACMPolicy(xml=xml)
|
||||
print "Policy installed on the system:"
|
||||
if acmpol:
|
||||
print "Policy name : %s" % acmpol.get_name()
|
||||
print "Policy type : %s" % xsconstants.ACM_POLICY_ID
|
||||
print "Reference : %s" % policystate['xs_ref']
|
||||
print "Version of XML policy : %s" % policystate['version']
|
||||
state = []
|
||||
flags = int(policystate['flags'])
|
||||
if flags & xsconstants.XS_INST_LOAD:
|
||||
state.append("loaded")
|
||||
if flags & xsconstants.XS_INST_BOOT:
|
||||
state.append("system booted with")
|
||||
print "State of the policy : %s" % ", ".join(state)
|
||||
if dumpxml:
|
||||
|
||||
def getpolicy(dumpxml):
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
xstype = int(server.xenapi.XSPolicy.get_xstype())
|
||||
display_security_subsystems(xstype)
|
||||
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
print "No policy is installed."
|
||||
return
|
||||
if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
|
||||
print "Unknown policy type '%s'." % policystate['type']
|
||||
else:
|
||||
xml = policystate['repr']
|
||||
acmpol = None
|
||||
if xml:
|
||||
dom = minidom.parseString(xml.encode("utf-8"))
|
||||
print "%s" % dom.toprettyxml(indent=" ",newl="\n")
|
||||
acmpol = ACMPolicy(xml=xml)
|
||||
|
||||
display_policy_info(acmpol,
|
||||
xsconstants.ACM_POLICY_ID,
|
||||
policystate['xs_ref'],
|
||||
policystate['version'],
|
||||
int(policystate['flags']),
|
||||
dumpxml,
|
||||
xml)
|
||||
else:
|
||||
xstype = server.xend.security.get_xstype()
|
||||
display_security_subsystems(xstype)
|
||||
|
||||
xml, flags = server.xend.security.get_policy()
|
||||
acmpol = None
|
||||
if xml != "":
|
||||
dom = None
|
||||
try:
|
||||
dom = minidom.parseString(xml)
|
||||
if dom:
|
||||
acmpol = ACMPolicy(dom=dom)
|
||||
except Exception, e:
|
||||
print "Error parsing the library: " + str(e)
|
||||
|
||||
if acmpol:
|
||||
display_policy_info(acmpol,
|
||||
xsconstants.ACM_POLICY_ID,
|
||||
None,
|
||||
acmpol.get_version(),
|
||||
flags,
|
||||
dumpxml,
|
||||
xml)
|
||||
else:
|
||||
print "No policy is installed."
|
||||
|
||||
def main(argv):
|
||||
dumpxml = False
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
"""
|
||||
import sys
|
||||
import traceback
|
||||
import string
|
||||
from xen.util.xsm.xsm import XSMError, err, list_labels, active_policy
|
||||
from xen.util.xsm.xsm import vm_label_re, res_label_re, all_label_re
|
||||
from xen.util.xsm.xsm import XSMError, err
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.util.acmpolicy import ACMPolicy
|
||||
from xen.util import xsconstants
|
||||
@@ -58,32 +56,12 @@ def main(argv):
|
||||
labels_xapi(policy, ptype)
|
||||
|
||||
def labels(policy, ptype):
|
||||
if not policy:
|
||||
policy = active_policy
|
||||
if active_policy in ['NULL', 'INACTIVE', 'DEFAULT']:
|
||||
raise OptionError('No policy active, you must specify a <policy>')
|
||||
if active_policy in ['INACCESSIBLE']:
|
||||
raise OptionError('Cannot access the policy. Try as root.')
|
||||
|
||||
if not ptype or ptype == 'dom':
|
||||
condition = vm_label_re
|
||||
elif ptype == 'res':
|
||||
condition = res_label_re
|
||||
elif ptype == 'any':
|
||||
condition = all_label_re
|
||||
else:
|
||||
err("Unknown label type \'" + ptype + "\'")
|
||||
labels = server.xend.security.list_labels(policy, ptype)
|
||||
labels.sort()
|
||||
for label in labels:
|
||||
print label
|
||||
|
||||
try:
|
||||
labels = list_labels(policy, condition)
|
||||
labels.sort()
|
||||
for label in labels:
|
||||
print label
|
||||
|
||||
except XSMError:
|
||||
sys.exit(-1)
|
||||
except:
|
||||
traceback.print_exc(limit = 1)
|
||||
|
||||
def labels_xapi(policy, ptype):
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2006 International Business Machines Corp.
|
||||
# Author: Reiner Sailer <sailer@us.ibm.com>
|
||||
#============================================================================
|
||||
|
||||
"""Loading a compiled binary policy into the hypervisor.
|
||||
"""
|
||||
import sys
|
||||
import traceback
|
||||
from xen.util.xsm.xsm import XSMError, err, load_policy
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
from xen.util import xsconstants
|
||||
from xen.xm.activatepolicy import activate_policy
|
||||
from xen.xm.main import server
|
||||
from xen.util.acmpolicy import ACMPolicy
|
||||
|
||||
def help():
|
||||
return """Load the compiled binary (.bin) policy into the running
|
||||
hypervisor."""
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 2:
|
||||
raise OptionError('No policy defined')
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
policy = argv[1]
|
||||
print "This command is deprecated for use with Xen-API " \
|
||||
"configuration. Consider using\n'xm activatepolicy'."
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
print "No policy is installed."
|
||||
return
|
||||
|
||||
if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
|
||||
print "Unknown policy type '%s'." % policystate['type']
|
||||
return
|
||||
else:
|
||||
xml = policystate['repr']
|
||||
xs_ref = policystate['xs_ref']
|
||||
if not xml:
|
||||
OptionError("No policy installed on system?")
|
||||
acmpol = ACMPolicy(xml=xml)
|
||||
if acmpol.get_name() != policy:
|
||||
OptionError("Policy installed on system '%s' does not match"\
|
||||
" the request policy '%s'" % \
|
||||
(acmpol.get_name(), policy))
|
||||
activate_policy(xsconstants.XS_INST_LOAD)
|
||||
else:
|
||||
load_policy(argv[1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(sys.argv)
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: %s\n' % str(e))
|
||||
sys.exit(-1)
|
||||
|
||||
@@ -187,16 +187,12 @@ SUBCOMMAND_HELP = {
|
||||
'dry-run' : ('<ConfigFile>',
|
||||
'Test if a domain can access its resources.'),
|
||||
'resources' : ('', 'Show info for each labeled resource.'),
|
||||
'cfgbootpolicy' : ('<policy> [boot-title]',
|
||||
'Add policy to boot configuration.'),
|
||||
'dumppolicy' : ('', 'Print hypervisor ACM state information.'),
|
||||
'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'),
|
||||
'makepolicy' : ('<policy>', 'Build policy and create .bin/.map '
|
||||
'files.'),
|
||||
'setpolicy' : ('<policytype> <policyfile> [options]',
|
||||
'Set the policy of the system.'),
|
||||
'resetpolicy' : ('',
|
||||
'Set the policy of the system to the default policy.'),
|
||||
'getpolicy' : ('[options]', 'Get the policy of the system.'),
|
||||
'activatepolicy': ('[options]', 'Activate the xend-managed policy.'),
|
||||
'labels' : ('[policy] [type=dom|res|any]',
|
||||
'List <type> labels for (active) policy.'),
|
||||
'serve' : ('', 'Proxy Xend XMLRPC over stdio.'),
|
||||
@@ -350,12 +346,9 @@ acm_commands = [
|
||||
"getlabel",
|
||||
"dry-run",
|
||||
"resources",
|
||||
"makepolicy",
|
||||
"loadpolicy",
|
||||
"cfgbootpolicy",
|
||||
"dumppolicy",
|
||||
"activatepolicy",
|
||||
"setpolicy",
|
||||
"resetpolicy",
|
||||
"getpolicy",
|
||||
]
|
||||
|
||||
@@ -942,18 +935,13 @@ def xm_label_list(doms):
|
||||
format = '%(name)-40s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \
|
||||
'%(cpu_time)8.1f %(seclabel)10s'
|
||||
|
||||
import xen.util.xsm.xsm as security
|
||||
|
||||
for dom in doms:
|
||||
d = parse_doms_info(dom)
|
||||
if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
|
||||
if not d['seclabel']:
|
||||
d['seclabel'] = ACM_LABEL_UNLABELED_DISPLAY
|
||||
elif security.active_policy in ['DEFAULT']:
|
||||
d['seclabel'] = 'DEFAULT'
|
||||
else:
|
||||
d['seclabel'] = 'INACTIVE'
|
||||
|
||||
if d['seclabel'] == "" and serverType != SERVER_XEN_API:
|
||||
seclab = server.xend.security.get_domain_label(d['name'])
|
||||
if len(seclab) > 0 and seclab[0] == '\'':
|
||||
seclab = seclab[1:]
|
||||
d['seclabel'] = seclab
|
||||
output.append((format % d, d['seclabel']))
|
||||
|
||||
#sort by labels
|
||||
@@ -2471,9 +2459,6 @@ IMPORTED_COMMANDS = [
|
||||
'new',
|
||||
'migrate',
|
||||
'labels',
|
||||
'cfgbootpolicy',
|
||||
'makepolicy',
|
||||
'loadpolicy',
|
||||
'dumppolicy',
|
||||
'addlabel',
|
||||
'rmlabel',
|
||||
@@ -2482,7 +2467,7 @@ IMPORTED_COMMANDS = [
|
||||
'resources',
|
||||
'getpolicy',
|
||||
'setpolicy',
|
||||
'activatepolicy',
|
||||
'resetpolicy',
|
||||
]
|
||||
|
||||
for c in IMPORTED_COMMANDS:
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2006 International Business Machines Corp.
|
||||
# Author: Reiner Sailer <sailer@us.ibm.com>
|
||||
#============================================================================
|
||||
"""Compiling a XML source policy file into mapping and binary versions.
|
||||
"""
|
||||
import sys
|
||||
import traceback
|
||||
from xen.util.xsm.xsm import ACMError, err, make_policy
|
||||
from xen.util import xsconstants
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.setpolicy import setpolicy
|
||||
|
||||
def usage():
|
||||
print "\nUsage: xm makepolicy <policy>\n"
|
||||
print " Translate an XML source policy and create"
|
||||
print " mapping file and binary policy.\n"
|
||||
err("Usage")
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 2:
|
||||
raise OptionError('No XML policy file specified')
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
print "This command is deprecated for use with Xen-API " \
|
||||
"configuration. Consider using\n'xm setpolicy'."
|
||||
setpolicy(xsconstants.ACM_POLICY_ID, argv[1],
|
||||
xsconstants.XS_INST_LOAD, True)
|
||||
else:
|
||||
make_policy(argv[1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(sys.argv)
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: %s\n' % str(e))
|
||||
sys.exit(-1)
|
||||
@@ -0,0 +1,162 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2007 International Business Machines Corp.
|
||||
# Author: Stefan Berger <stefanb@us.ibm.com>
|
||||
#============================================================================
|
||||
""" Reset the system's current policy to the default state.
|
||||
"""
|
||||
import sys
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util.xsm.xsm import XSMError
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.main import server
|
||||
from xen.util import xsconstants
|
||||
from xen.util.acmpolicy import ACMPolicy
|
||||
|
||||
DOM0_UUID = "00000000-0000-0000-0000-000000000000"
|
||||
|
||||
DEFAULT_policy_template = \
|
||||
"<?xml version=\"1.0\" ?>" +\
|
||||
"<SecurityPolicyDefinition xmlns=\"http://www.ibm.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.ibm.com ../../security_policy.xsd\">" +\
|
||||
" <PolicyHeader>" +\
|
||||
" <PolicyName>DEFAULT</PolicyName>" +\
|
||||
" <Version>1.0</Version>" +\
|
||||
" </PolicyHeader>" +\
|
||||
" <SimpleTypeEnforcement>" +\
|
||||
" <SimpleTypeEnforcementTypes>" +\
|
||||
" <Type>SystemManagement</Type>" +\
|
||||
" </SimpleTypeEnforcementTypes>" +\
|
||||
" </SimpleTypeEnforcement>" +\
|
||||
" <ChineseWall>" +\
|
||||
" <ChineseWallTypes>" +\
|
||||
" <Type>SystemManagement</Type>" +\
|
||||
" </ChineseWallTypes>" +\
|
||||
" </ChineseWall>" +\
|
||||
" <SecurityLabelTemplate>" +\
|
||||
" <SubjectLabels bootstrap=\"SystemManagement\">" +\
|
||||
" <VirtualMachineLabel>" +\
|
||||
" <Name%s>SystemManagement</Name>" +\
|
||||
" <SimpleTypeEnforcementTypes>" +\
|
||||
" <Type>SystemManagement</Type>" +\
|
||||
" </SimpleTypeEnforcementTypes>" +\
|
||||
" <ChineseWallTypes>" +\
|
||||
" <Type/>" +\
|
||||
" </ChineseWallTypes>" +\
|
||||
" </VirtualMachineLabel>" +\
|
||||
" </SubjectLabels>" +\
|
||||
" </SecurityLabelTemplate>" +\
|
||||
"</SecurityPolicyDefinition>"
|
||||
|
||||
|
||||
def help():
|
||||
return """
|
||||
Reset the system's policy to the default.
|
||||
|
||||
When the system's policy is reset, all guest VMs should be halted,
|
||||
since otherwise this operation will fail.
|
||||
"""
|
||||
|
||||
def get_reset_policy_xml(dom0_seclab):
|
||||
if dom0_seclab == "":
|
||||
return DEFAULT_policy_template % ""
|
||||
else:
|
||||
poltyp, policy, label = dom0_seclab.split(":")
|
||||
if label != "SystemManagement":
|
||||
return DEFAULT_policy_template % \
|
||||
(" from=\"%s\"" % label)
|
||||
else:
|
||||
return DEFAULT_policy_template % ""
|
||||
|
||||
def resetpolicy():
|
||||
msg = None
|
||||
xs_type = xsconstants.XS_POLICY_ACM
|
||||
flags = xsconstants.XS_INST_LOAD
|
||||
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
if int(server.xenapi.XSPolicy.get_xstype()) & xs_type == 0:
|
||||
raise security.XSMError("ACM policy type not supported.")
|
||||
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
|
||||
acmpol = ACMPolicy(xml=policystate['repr'])
|
||||
|
||||
now_flags = int(policystate['flags'])
|
||||
|
||||
if now_flags & xsconstants.XS_INST_BOOT == 0 and \
|
||||
not acmpol.is_default_policy():
|
||||
msg = "Old policy not found in bootloader file."
|
||||
|
||||
seclab = server.xenapi.VM.get_security_label(DOM0_UUID)
|
||||
xml = get_reset_policy_xml(seclab)
|
||||
try:
|
||||
policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
|
||||
xml,
|
||||
flags,
|
||||
True)
|
||||
except Exception, e:
|
||||
raise security.XSMError("An error occurred resetting the "
|
||||
"policy: %s" % str(e))
|
||||
|
||||
xserr = int(policystate['xserr'])
|
||||
if xserr != xsconstants.XSERR_SUCCESS:
|
||||
raise security.XSMError("Could not reset the system's policy. "
|
||||
"Try to halt all guests.")
|
||||
else:
|
||||
print "Successfully reset the system's policy."
|
||||
if msg:
|
||||
print msg
|
||||
else:
|
||||
if server.xend.security.get_xstype() & xs_type == 0:
|
||||
raise security.XSMError("ACM policy type not supported.")
|
||||
|
||||
xml, now_flags = server.xend.security.get_policy()
|
||||
|
||||
acmpol = ACMPolicy(xml=xml)
|
||||
|
||||
if int(now_flags) & xsconstants.XS_INST_BOOT == 0 and \
|
||||
not acmpol.is_default_policy():
|
||||
msg = "Old policy not found in bootloader file."
|
||||
|
||||
seclab = server.xend.security.get_domain_label(0)
|
||||
if seclab[0] == '\'':
|
||||
seclab = seclab[1:]
|
||||
xml = get_reset_policy_xml(seclab)
|
||||
rc, errors = server.xend.security.set_policy(xs_type,
|
||||
xml,
|
||||
flags,
|
||||
True)
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
raise security.XSMError("Could not reset the system's policy. "
|
||||
"Try to halt all guests.")
|
||||
else:
|
||||
print "Successfully reset the system's policy."
|
||||
if msg:
|
||||
print msg
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 1:
|
||||
raise OptionError("No arguments expected.")
|
||||
|
||||
resetpolicy()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(sys.argv)
|
||||
except Exception, e:
|
||||
sys.stderr.write('Error: %s\n' % str(e))
|
||||
sys.exit(-1)
|
||||
@@ -19,8 +19,6 @@
|
||||
"""List the resource label information from the global resource label file
|
||||
"""
|
||||
import sys
|
||||
from xen.util import dictio
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util import xsconstants
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
@@ -55,11 +53,7 @@ def main (argv):
|
||||
for key, value in access_control.items():
|
||||
access_control[key] = tuple(value.split(':'))
|
||||
else:
|
||||
try:
|
||||
filename = security.res_label_filename
|
||||
access_control = dictio.dict_read("resources", filename)
|
||||
except:
|
||||
raise OptionError("Resource file not found")
|
||||
access_control = server.xend.security.get_labeled_resources()
|
||||
|
||||
print_resource_data(access_control)
|
||||
|
||||
|
||||
@@ -18,9 +18,12 @@
|
||||
|
||||
"""Remove a label from a domain configuration file or a resoruce.
|
||||
"""
|
||||
import sys, os, re
|
||||
from xen.util import dictio
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util import xsconstants
|
||||
from xen.util.acmpolicy import ACM_LABEL_UNLABELED
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.main import server
|
||||
@@ -33,10 +36,11 @@ def help():
|
||||
xm rmlabel vif-<idx> <domain name>
|
||||
|
||||
This program removes an acm_label entry from the 'configfile'
|
||||
for a domain, from a Xend-managed domain, from the global resource label
|
||||
file for a resource or from the virtual network interface of a Xend-managed
|
||||
domain. If the label does not exist for the given domain or resource, then
|
||||
rmlabel fails."""
|
||||
for a domain, the label from a Xend-managed domain or a resources
|
||||
or from the network interface of a Xend-managed domain (requires
|
||||
xm to be used in Xen-API mode). If the label does not exist for
|
||||
the given domain or resource, then rmlabel fails and reports an error.
|
||||
"""
|
||||
|
||||
|
||||
def rm_resource_label(resource):
|
||||
@@ -55,24 +59,19 @@ def rm_resource_label(resource):
|
||||
raise security.XSMError("Could not remove label "
|
||||
"from resource: %s" % e)
|
||||
return
|
||||
|
||||
#build canonical resource name
|
||||
resource = security.unify_resname(resource)
|
||||
|
||||
# read in the resource file
|
||||
fil = security.res_label_filename
|
||||
try:
|
||||
access_control = dictio.dict_read("resources", fil)
|
||||
except:
|
||||
raise security.ACMError("Resource file not found, cannot remove label!")
|
||||
|
||||
# remove the entry and update file
|
||||
if access_control.has_key(resource):
|
||||
del access_control[resource]
|
||||
dictio.dict_write(access_control, "resources", fil)
|
||||
else:
|
||||
raise security.ACMError("Resource not labeled")
|
||||
|
||||
oldlabel = server.xend.security.get_resource_label(resource)
|
||||
if len(oldlabel) != 0:
|
||||
rc = server.xend.security.set_resource_label(resource,
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
raise security.XSMError("An error occurred removing the "
|
||||
"label: %s" % \
|
||||
xsconstants.xserr2string(-rc))
|
||||
else:
|
||||
raise security.XSMError("Resource not labeled")
|
||||
|
||||
def rm_domain_label(configfile):
|
||||
# open the domain config file
|
||||
@@ -116,20 +115,43 @@ def rm_domain_label(configfile):
|
||||
fd.writelines(file_contents)
|
||||
fd.close()
|
||||
|
||||
def rm_domain_label_xapi(domainname):
|
||||
def rm_domain_label_xapi(domain):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('Need to be configure for using xen-api.')
|
||||
uuids = server.xenapi.VM.get_by_name_label(domainname)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('Too many domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
try:
|
||||
old_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
server.xenapi.VM.set_security_label(uuid, "", old_lab)
|
||||
except Exception, e:
|
||||
raise security.XSMError('Could not remove label from domain: %s' % e)
|
||||
old_lab = server.xend.security.get_domain_label(domain)
|
||||
|
||||
vmlabel = ""
|
||||
if old_lab != "":
|
||||
tmp = old_lab.split(":")
|
||||
if len(tmp) == 3:
|
||||
vmlabel = tmp[2]
|
||||
|
||||
if old_lab != "" and vmlabel != ACM_LABEL_UNLABELED:
|
||||
server.xend.security.set_domain_label(domain, "", old_lab)
|
||||
print "Successfully removed label from domain %s." % domain
|
||||
else:
|
||||
raise security.XSMError("Domain was not labeled.")
|
||||
else:
|
||||
uuids = server.xenapi.VM.get_by_name_label(domain)
|
||||
if len(uuids) == 0:
|
||||
raise OptionError('A VM with that name does not exist.')
|
||||
if len(uuids) != 1:
|
||||
raise OptionError('Too many domains with the same name.')
|
||||
uuid = uuids[0]
|
||||
try:
|
||||
old_lab = server.xenapi.VM.get_security_label(uuid)
|
||||
|
||||
vmlabel = ""
|
||||
if old_lab != "":
|
||||
tmp = old_lab.split(":")
|
||||
if len(tmp) == 3:
|
||||
vmlabel = tmp[2]
|
||||
|
||||
if old_lab != "":
|
||||
server.xenapi.VM.set_security_label(uuid, "", old_lab)
|
||||
else:
|
||||
raise security.XSMError("Domain was not labeled.")
|
||||
except Exception, e:
|
||||
raise security.XSMError('Could not remove label from domain: %s' % e)
|
||||
|
||||
def rm_vif_label(vmname, idx):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
|
||||
@@ -19,106 +19,128 @@
|
||||
"""Get the managed policy of the system.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import struct
|
||||
import sys
|
||||
import string
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util import xsconstants
|
||||
from xen.util.acmpolicy import ACMPolicy
|
||||
from xen.util.acmpolicy import ACMPolicy, \
|
||||
ACM_EVTCHN_SHARING_VIOLATION,\
|
||||
ACM_GNTTAB_SHARING_VIOLATION, \
|
||||
ACM_DOMAIN_LOOKUP, \
|
||||
ACM_CHWALL_CONFLICT, \
|
||||
ACM_SSIDREF_IN_USE
|
||||
from xen.xm.opts import OptionError
|
||||
from xen.util.xsm.acm.acm import policy_dir_prefix
|
||||
from xen.xm import main as xm_main
|
||||
from xen.xm.getpolicy import getpolicy
|
||||
from xen.xm.main import server
|
||||
|
||||
def help():
|
||||
return """
|
||||
Usage: xm setpolicy <policytype> <policy> [options]
|
||||
Usage: xm setpolicy <policytype> <policyname>
|
||||
|
||||
Set the policy managed by xend.
|
||||
|
||||
The only policytype that is currently supported is 'ACM'.
|
||||
|
||||
The following options are defined
|
||||
--load Load the policy immediately
|
||||
--boot Have the system load the policy during boot
|
||||
--update Automatically adapt the policy so that it will be
|
||||
treated as an update to the current policy
|
||||
The filename of the policy is the policy name plus the suffic
|
||||
'-security_policy.xml'. The location of the policy file is either
|
||||
the the current directory or '/etc/xen/acm-security/policies'.
|
||||
|
||||
"""
|
||||
|
||||
def create_update_xml(xml):
|
||||
def build_hv_error_message(errors):
|
||||
"""
|
||||
Adapt the new policy's xml header to be a simple type of an
|
||||
update to the currently enforce policy on the remote system.
|
||||
Increases the minor number by '1'.
|
||||
Build a message from the error codes return by the hypervisor.
|
||||
"""
|
||||
policystate = server.xenapi.XSPolicy.get_xspolicy()
|
||||
if int(policystate['type']) == 0:
|
||||
return xml
|
||||
curpol = ACMPolicy(xml = policystate['repr'])
|
||||
curpol_version = curpol.get_version()
|
||||
tmp = curpol_version.split('.')
|
||||
if len(tmp) == 2:
|
||||
maj = int(tmp[0])
|
||||
min = int(tmp[1])
|
||||
else:
|
||||
maj = int(tmp)
|
||||
min = 0
|
||||
min += 1
|
||||
newpol_version = ""+str(maj)+"."+str(min)
|
||||
txt = "Hypervisor reported errors:"
|
||||
i = 0
|
||||
while i + 7 < len(errors):
|
||||
code, data = struct.unpack("!ii", errors[i:i+8])
|
||||
err_msgs = {
|
||||
ACM_EVTCHN_SHARING_VIOLATION : \
|
||||
["event channel sharing violation between domains",2],
|
||||
ACM_GNTTAB_SHARING_VIOLATION : \
|
||||
["grant table sharing violation between domains",2],
|
||||
ACM_DOMAIN_LOOKUP : \
|
||||
["domain lookup",1],
|
||||
ACM_CHWALL_CONFLICT : \
|
||||
["Chinese Wall conflict between domains",2],
|
||||
ACM_SSIDREF_IN_USE : \
|
||||
["A domain used SSIDREF",1],
|
||||
}
|
||||
num = err_msgs[code][1]
|
||||
if num == 1:
|
||||
txt += "%s %d" % (err_msgs[code][0], data)
|
||||
else:
|
||||
txt += "%s %d and %d" % (err_msgs[code][0],
|
||||
data >> 16 , data & 0xffff)
|
||||
i += 8
|
||||
return txt
|
||||
|
||||
newpol = ACMPolicy(xml = xml)
|
||||
newpol.set_frompolicy_name(curpol.get_name())
|
||||
newpol.set_frompolicy_version(curpol.get_version())
|
||||
newpol.set_policy_version(newpol_version)
|
||||
return newpol.toxml()
|
||||
|
||||
def setpolicy(policytype, policy_name, flags, overwrite, is_update=False):
|
||||
if xm_main.serverType != xm_main.SERVER_XEN_API:
|
||||
raise OptionError('xm needs to be configured to use the xen-api.')
|
||||
if policytype != xsconstants.ACM_POLICY_ID:
|
||||
raise OptionError("Unsupported policytype '%s'." % policytype)
|
||||
else:
|
||||
def setpolicy(policytype, policy_name, flags, overwrite):
|
||||
|
||||
if policytype.upper() == xsconstants.ACM_POLICY_ID:
|
||||
xs_type = xsconstants.XS_POLICY_ACM
|
||||
|
||||
policy_file = policy_dir_prefix + "/" + \
|
||||
string.join(string.split(policy_name, "."), "/")
|
||||
policy_file += "-security_policy.xml"
|
||||
for prefix in [ './', policy_dir_prefix+"/" ]:
|
||||
policy_file = prefix + "/".join(policy_name.split(".")) + \
|
||||
"-security_policy.xml"
|
||||
|
||||
if os.path.exists(policy_file):
|
||||
break
|
||||
|
||||
try:
|
||||
f = open(policy_file,"r")
|
||||
xml = f.read(-1)
|
||||
xml = f.read()
|
||||
f.close()
|
||||
except:
|
||||
raise OptionError("Not a valid policy file")
|
||||
raise OptionError("Could not read policy file from current"
|
||||
" directory or '%s'." % policy_dir_prefix)
|
||||
|
||||
if is_update:
|
||||
xml = create_update_xml(xml)
|
||||
if xm_main.serverType == xm_main.SERVER_XEN_API:
|
||||
|
||||
try:
|
||||
policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
|
||||
xml,
|
||||
flags,
|
||||
overwrite)
|
||||
except Exception, e:
|
||||
raise security.XSMError("An error occurred setting the "
|
||||
"policy: %s" % str(e))
|
||||
xserr = int(policystate['xserr'])
|
||||
if xserr != 0:
|
||||
txt = "An error occurred trying to set the policy: %s." % \
|
||||
xsconstants.xserr2string(abs(xserr))
|
||||
errors = policystate['errors']
|
||||
if len(errors) > 0:
|
||||
txt += "Hypervisor reported errors:"
|
||||
err = base64.b64decode(errors)
|
||||
i = 0
|
||||
while i + 7 < len(err):
|
||||
code, data = struct.unpack("!ii", errors[i:i+8])
|
||||
txt += "(0x%08x, 0x%08x)" % (code, data)
|
||||
i += 8
|
||||
raise security.XSMError(txt)
|
||||
try:
|
||||
policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
|
||||
xml,
|
||||
flags,
|
||||
overwrite)
|
||||
except Exception, e:
|
||||
raise security.XSMError("An error occurred setting the "
|
||||
"policy: %s" % str(e))
|
||||
xserr = int(policystate['xserr'])
|
||||
if xserr != xsconstants.XSERR_SUCCESS:
|
||||
txt = "An error occurred trying to set the policy: %s." % \
|
||||
xsconstants.xserr2string(abs(xserr))
|
||||
errors = policystate['errors']
|
||||
if len(errors) > 0:
|
||||
txt += " " + build_hv_error_message(base64.b64decode(errors))
|
||||
raise security.XSMError(txt)
|
||||
else:
|
||||
print "Successfully set the new policy."
|
||||
getpolicy(False)
|
||||
else:
|
||||
print "Successfully set the new policy."
|
||||
# Non-Xen-API call.
|
||||
|
||||
rc, errors = server.xend.security.set_policy(xs_type,
|
||||
xml,
|
||||
flags,
|
||||
overwrite)
|
||||
if rc != xsconstants.XSERR_SUCCESS:
|
||||
txt = "An error occurred trying to set the policy: %s." % \
|
||||
xsconstants.xserr2string(abs(rc))
|
||||
if len(errors) > 0:
|
||||
txt += " " + build_hv_error_message(
|
||||
base64.b64decode(errors))
|
||||
raise security.XSMError(txt)
|
||||
else:
|
||||
print "Successfully set the new policy."
|
||||
getpolicy(False)
|
||||
else:
|
||||
raise OptionError("Unsupported policytype '%s'." % policytype)
|
||||
|
||||
|
||||
def main(argv):
|
||||
@@ -131,21 +153,11 @@ def main(argv):
|
||||
|
||||
policytype = argv[1]
|
||||
policy_name = argv[2]
|
||||
is_update = False
|
||||
|
||||
flags = 0
|
||||
if '--load' in argv:
|
||||
flags |= xsconstants.XS_INST_LOAD
|
||||
if '--boot' in argv:
|
||||
flags |= xsconstants.XS_INST_BOOT
|
||||
if '--update' in argv:
|
||||
is_update = True
|
||||
|
||||
flags = xsconstants.XS_INST_LOAD | xsconstants.XS_INST_BOOT
|
||||
overwrite = True
|
||||
if '--nooverwrite' in argv:
|
||||
overwrite = False
|
||||
|
||||
setpolicy(policytype, policy_name, flags, overwrite, is_update)
|
||||
setpolicy(policytype, policy_name, flags, overwrite)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
|
||||
@@ -15,12 +15,10 @@ LDFLAGS += $(shell xml2-config --libs ) # if this does not work, try -L/usr/l
|
||||
|
||||
SRCS_TOOL = secpol_tool.c
|
||||
OBJS_TOOL := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_TOOL)))
|
||||
SRCS_XML2BIN = secpol_xml2bin.c secpol_xml2bin.h
|
||||
OBJS_XML2BIN := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_XML2BIN)))
|
||||
|
||||
ACM_INST_TOOLS = xensec_tool xensec_xml2bin xensec_gen
|
||||
ACM_INST_TOOLS = xensec_tool xensec_gen
|
||||
ACM_EZPOLICY = xensec_ezpolicy
|
||||
ACM_OBJS = $(OBJS_TOOL) $(OBJS_XML2BIN) $(OBJS_GETD)
|
||||
ACM_OBJS = $(OBJS_TOOL) $(OBJS_GETD)
|
||||
ACM_SCRIPTS = python/xensec_tools/acm_getlabel
|
||||
|
||||
ACM_CONFIG_DIR = /etc/xen/acm-security
|
||||
@@ -86,9 +84,6 @@ build: $(ACM_INST_TOOLS) $(ACM_NOINST_TOOLS)
|
||||
xensec_tool: $(OBJS_TOOL)
|
||||
$(CC) -g $(CFLAGS) $(LDFLAGS) -O0 -o $@ $^ -L$(XEN_LIBXC) -lxenctrl
|
||||
|
||||
xensec_xml2bin: $(OBJS_XML2BIN)
|
||||
$(CC) -g $(CFLAGS) $(LDFLAGS) -O0 -o $@ $^
|
||||
|
||||
xensec_gen: xensec_gen.py
|
||||
cp -f $^ $@
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</ConflictSets>
|
||||
</ChineseWall>
|
||||
<SecurityLabelTemplate>
|
||||
<SubjectLabels bootstrap="dom_SystemManagement">
|
||||
<SubjectLabels bootstrap="SystemManagement">
|
||||
<!-- single ste typed domains -->
|
||||
<!-- ACM enforces that only domains with -->
|
||||
<!-- the same type can share information -->
|
||||
@@ -89,7 +89,7 @@
|
||||
<!-- Domains with multiple ste types services; such domains -->
|
||||
<!-- must keep the types inside their domain safely confined. -->
|
||||
<VirtualMachineLabel>
|
||||
<Name>dom_SystemManagement</Name>
|
||||
<Name>SystemManagement</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<!-- since dom0 needs access to every domain and -->
|
||||
<!-- resource right now ... -->
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Author: Reiner Sailer, Ray Valdez {sailer,rvaldez}@us.ibm.com -->
|
||||
<!-- This file defines the security policies, which -->
|
||||
<!-- can be enforced by the Xen Access Control Module. -->
|
||||
<!-- Currently: Chinese Wall and Simple Type Enforcement-->
|
||||
<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
|
||||
<PolicyHeader>
|
||||
<PolicyName>example.ste.client_v1</PolicyName>
|
||||
<PolicyUrl>www.ibm.com/example/ste/client_v1</PolicyUrl>
|
||||
<Date>2006-03-31</Date>
|
||||
</PolicyHeader>
|
||||
<!-- -->
|
||||
<!-- example of a simple type enforcement policy definition -->
|
||||
<!-- -->
|
||||
<SimpleTypeEnforcement>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_SystemManagement</Type><!-- machine/security management -->
|
||||
<Type>ste_PersonalFinances</Type><!-- personal finances -->
|
||||
<Type>ste_InternetInsecure</Type><!-- games, active X, etc. -->
|
||||
<Type>ste_DonatedCycles</Type><!-- donation to BOINC/seti@home -->
|
||||
<Type>ste_PersistentStorageA</Type><!-- domain managing the harddrive A-->
|
||||
<Type>ste_NetworkAdapter0</Type><!-- type of the domain managing ethernet adapter 0-->
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</SimpleTypeEnforcement>
|
||||
<SecurityLabelTemplate>
|
||||
<SubjectLabels bootstrap="dom_SystemManagement">
|
||||
<!-- single ste typed domains -->
|
||||
<!-- ACM enforces that only domains with -->
|
||||
<!-- the same type can share information -->
|
||||
<!-- -->
|
||||
<!-- Bootstrap label is assigned to Dom0 -->
|
||||
<VirtualMachineLabel>
|
||||
<Name>dom_HomeBanking</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
|
||||
<VirtualMachineLabel>
|
||||
<Name>dom_Fun</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_InternetInsecure</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
|
||||
<VirtualMachineLabel>
|
||||
<!-- donating some cycles to seti@home -->
|
||||
<Name>dom_BoincClient</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_DonatedCycles</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
|
||||
<!-- Domains with multiple ste types services; such domains -->
|
||||
<!-- must keep the types inside their domain safely confined. -->
|
||||
<VirtualMachineLabel>
|
||||
<Name>dom_SystemManagement</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<!-- since dom0 needs access to every domain and -->
|
||||
<!-- resource right now ... -->
|
||||
<Type>ste_SystemManagement</Type>
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
<Type>ste_InternetInsecure</Type>
|
||||
<Type>ste_DonatedCycles</Type>
|
||||
<Type>ste_PersistentStorageA</Type>
|
||||
<Type>ste_NetworkAdapter0</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
|
||||
<VirtualMachineLabel>
|
||||
<!-- serves persistent storage to other domains -->
|
||||
<Name>dom_StorageDomain</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<!-- access right to the resource (hard drive a) -->
|
||||
<Type>ste_PersistentStorageA</Type>
|
||||
<!-- can serve following types -->
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
<Type>ste_InternetInsecure</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
|
||||
<VirtualMachineLabel>
|
||||
<!-- serves network access to other domains -->
|
||||
<Name>dom_NetworkDomain</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<!-- access right to the resource (ethernet card) -->
|
||||
<Type>ste_NetworkAdapter0</Type>
|
||||
<!-- can serve following types -->
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
<Type>ste_InternetInsecure</Type>
|
||||
<Type>ste_DonatedCycles</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</VirtualMachineLabel>
|
||||
</SubjectLabels>
|
||||
|
||||
<ObjectLabels>
|
||||
<ResourceLabel>
|
||||
<Name>res_ManagementResource</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_SystemManagement</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_HardDrive(hda)</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_PersistentStorageA</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_LogicalDiskPartition1(hda1)</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_LogicalDiskPartition2(hda2)</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_InternetInsecure</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_EthernetCard</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_NetworkAdapter0</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_SecurityToken</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_PersonalFinances</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
|
||||
<ResourceLabel>
|
||||
<Name>res_GraphicsAdapter</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>ste_SystemManagement</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
</ResourceLabel>
|
||||
</ObjectLabels>
|
||||
</SecurityLabelTemplate>
|
||||
|
||||
</SecurityPolicyDefinition>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,166 +0,0 @@
|
||||
/****************************************************************
|
||||
* secpol_xml2bin.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
*/
|
||||
#define POLICY_DIR "/etc/xen/acm-security/policies/"
|
||||
#define POLICY_EXTENSION "-security_policy.xml"
|
||||
#define BINARY_EXTENSION ".bin"
|
||||
#define MAPPING_EXTENSION ".map"
|
||||
#define PRIMARY_COMPONENT_ATTR_NAME "order"
|
||||
#define BOOTSTRAP_LABEL_ATTR_NAME "bootstrap"
|
||||
#define PRIMARY_COMPONENT "PrimaryPolicyComponent"
|
||||
#define SCHEMA_FILENAME "security_policy.xsd"
|
||||
|
||||
/* basic states (used as 1 << X) */
|
||||
enum {
|
||||
XML2BIN_SECPOL = 0, /* policy tokens */
|
||||
XML2BIN_STE,
|
||||
XML2BIN_CHWALL,
|
||||
XML2BIN_CONFLICTSETS,
|
||||
XML2BIN_CSTYPE,
|
||||
XML2BIN_POLICYHEADER,
|
||||
XML2BIN_NSURL,
|
||||
XML2BIN_POLICYNAME,
|
||||
XML2BIN_URL,
|
||||
XML2BIN_REFERENCE,
|
||||
XML2BIN_DATE,
|
||||
XML2BIN_VERSION,
|
||||
XML2BIN_FROMPOLICY,
|
||||
|
||||
XML2BIN_LABELTEMPLATE, /* label tokens */
|
||||
XML2BIN_SUBJECTS,
|
||||
XML2BIN_OBJECTS,
|
||||
XML2BIN_VM,
|
||||
XML2BIN_RES,
|
||||
XML2BIN_NAME,
|
||||
|
||||
XML2BIN_STETYPES,
|
||||
XML2BIN_CHWALLTYPES,
|
||||
XML2BIN_TYPE,
|
||||
XML2BIN_TEXT,
|
||||
XML2BIN_COMMENT,
|
||||
ENDOFLIST_POS /* keep last ! */
|
||||
};
|
||||
|
||||
/* type "data type" (currently 16bit) */
|
||||
typedef u_int16_t type_t;
|
||||
|
||||
/* list of known elements and token equivalent *
|
||||
* state constants and token positions must be *
|
||||
* in sync for correct state recognition */
|
||||
|
||||
char *token[32] = /* parser triggers */
|
||||
{
|
||||
[XML2BIN_SECPOL] = "SecurityPolicyDefinition", /* policy xml */
|
||||
[XML2BIN_STE] = "SimpleTypeEnforcement",
|
||||
[XML2BIN_CHWALL] = "ChineseWall",
|
||||
[XML2BIN_CONFLICTSETS] = "ConflictSets",
|
||||
[XML2BIN_CSTYPE] = "Conflict",
|
||||
[XML2BIN_POLICYHEADER] = "PolicyHeader",
|
||||
[XML2BIN_NSURL] = "NameSpaceUrl",
|
||||
[XML2BIN_POLICYNAME] = "PolicyName",
|
||||
[XML2BIN_URL] = "PolicyUrl",
|
||||
[XML2BIN_REFERENCE] = "Reference",
|
||||
[XML2BIN_DATE] = "Date",
|
||||
[XML2BIN_VERSION] = "Version",
|
||||
[XML2BIN_FROMPOLICY] = "FromPolicy",
|
||||
|
||||
[XML2BIN_LABELTEMPLATE] = "SecurityLabelTemplate", /* label-template xml */
|
||||
[XML2BIN_SUBJECTS] = "SubjectLabels",
|
||||
[XML2BIN_OBJECTS] = "ObjectLabels",
|
||||
[XML2BIN_VM] = "VirtualMachineLabel",
|
||||
[XML2BIN_RES] = "ResourceLabel",
|
||||
[XML2BIN_NAME] = "Name",
|
||||
|
||||
[XML2BIN_STETYPES] = "SimpleTypeEnforcementTypes", /* common tags */
|
||||
[XML2BIN_CHWALLTYPES] = "ChineseWallTypes",
|
||||
[XML2BIN_TYPE] = "Type",
|
||||
[XML2BIN_TEXT] = "text",
|
||||
[XML2BIN_COMMENT] = "comment",
|
||||
[ENDOFLIST_POS] = NULL /* End of LIST, adapt ENDOFLIST_POS
|
||||
when adding entries */
|
||||
};
|
||||
|
||||
/* important combined states */
|
||||
#define XML2BIN_NULL 0
|
||||
|
||||
/* policy xml parsing states _S */
|
||||
|
||||
/* e.g., here we are in a <secpol,ste,stetypes> environment, *
|
||||
* so when finding a type element, we know where to put it */
|
||||
#define XML2BIN_stetype_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_STE) | \
|
||||
(1 << XML2BIN_STETYPES))
|
||||
|
||||
#define XML2BIN_chwalltype_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_CHWALL) | \
|
||||
(1 << XML2BIN_CHWALLTYPES))
|
||||
|
||||
#define XML2BIN_conflictset_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_CHWALL) | \
|
||||
(1 << XML2BIN_CONFLICTSETS))
|
||||
|
||||
#define XML2BIN_conflictsettype_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_CHWALL) | \
|
||||
(1 << XML2BIN_CONFLICTSETS) | \
|
||||
(1 << XML2BIN_CSTYPE))
|
||||
|
||||
#define XML2BIN_PN_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_POLICYHEADER))
|
||||
|
||||
#define XML2BIN_PN_frompolicy_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_POLICYHEADER) | \
|
||||
(1 << XML2BIN_FROMPOLICY))
|
||||
|
||||
/* label xml states */
|
||||
#define XML2BIN_VM_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_LABELTEMPLATE) | \
|
||||
(1 << XML2BIN_SUBJECTS) | \
|
||||
(1 << XML2BIN_VM))
|
||||
|
||||
#define XML2BIN_RES_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_LABELTEMPLATE) | \
|
||||
(1 << XML2BIN_OBJECTS) | \
|
||||
(1 << XML2BIN_RES))
|
||||
|
||||
#define XML2BIN_VM_STE_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_LABELTEMPLATE) | \
|
||||
(1 << XML2BIN_SUBJECTS) | \
|
||||
(1 << XML2BIN_VM) | \
|
||||
(1 << XML2BIN_STETYPES))
|
||||
|
||||
#define XML2BIN_VM_CHWALL_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_LABELTEMPLATE) | \
|
||||
(1 << XML2BIN_SUBJECTS) | \
|
||||
(1 << XML2BIN_VM) | \
|
||||
(1 << XML2BIN_CHWALLTYPES))
|
||||
|
||||
#define XML2BIN_RES_STE_S ((1 << XML2BIN_SECPOL) | \
|
||||
(1 << XML2BIN_LABELTEMPLATE) | \
|
||||
(1 << XML2BIN_OBJECTS) | \
|
||||
(1 << XML2BIN_RES) | \
|
||||
(1 << XML2BIN_STETYPES))
|
||||
|
||||
|
||||
/* check versions of headers against which the
|
||||
* xml2bin translation tool was written
|
||||
*/
|
||||
|
||||
/* protects from unnoticed changes in struct acm_policy_buffer */
|
||||
#define WRITTEN_AGAINST_ACM_POLICY_VERSION 3
|
||||
|
||||
/* protects from unnoticed changes in struct acm_chwall_policy_buffer */
|
||||
#define WRITTEN_AGAINST_ACM_CHWALL_VERSION 1
|
||||
|
||||
/* protects from unnoticed changes in struct acm_ste_policy_buffer */
|
||||
#define WRITTEN_AGAINST_ACM_STE_VERSION 1
|
||||
@@ -34,56 +34,20 @@ acm_verbose = False
|
||||
def isACMEnabled():
|
||||
return security.on()
|
||||
|
||||
|
||||
def getSystemPolicyName():
|
||||
s,o = traceCommand("xm getpolicy")
|
||||
m = re.compile("Policy name[\s]*: ([A-z\-]+)").search(o)
|
||||
if m:
|
||||
polname = m.group(1)
|
||||
return polname
|
||||
return ""
|
||||
|
||||
|
||||
def ACMLoadPolicy_XenAPI(policy='xm-test'):
|
||||
polname = getSystemPolicyName()
|
||||
if polname != policy:
|
||||
# Try it, maybe it's not activated
|
||||
traceCommand("xm setpolicy %s %s" %
|
||||
(xsconstants.ACM_POLICY_ID, policy))
|
||||
polname = getSystemPolicyName()
|
||||
if polname != policy:
|
||||
FAIL("Need to have a system with no or policy '%s' active, "
|
||||
"not %s" % (policy,polname))
|
||||
else:
|
||||
s, o = traceCommand("xm activatepolicy --load")
|
||||
else:
|
||||
s, o = traceCommand("xm activatepolicy --load")
|
||||
if not re.search("Successfully", o):
|
||||
FAIL("Could not set the policy '%s'." % policy)
|
||||
|
||||
|
||||
def ACMLoadPolicy(policy='xm-test'):
|
||||
from xen.xm import main
|
||||
if main.serverType == main.SERVER_XEN_API:
|
||||
ACMLoadPolicy_XenAPI()
|
||||
else:
|
||||
cmd='xm dumppolicy | grep -E "^POLICY REFERENCE = ' + policy + '.$"'
|
||||
s, o = traceCommand(cmd)
|
||||
if o != "":
|
||||
return
|
||||
s, o = traceCommand("xm makepolicy %s" % (policy))
|
||||
if s != 0:
|
||||
FAIL("Need to be able to do 'xm makepolicy %s' but could not" %
|
||||
(policy))
|
||||
s, o = traceCommand("xm loadpolicy %s" % (policy))
|
||||
if s != 0:
|
||||
FAIL("Could not load the required policy '%s'.\n"
|
||||
"Start the system without any policy.\n%s" %
|
||||
(policy, o))
|
||||
def ACMSetPolicy(policy='xm-test'):
|
||||
cmd='xm dumppolicy | grep -E "^POLICY REFERENCE = ' + policy + '.$"'
|
||||
s, o = traceCommand(cmd)
|
||||
if o != "":
|
||||
return
|
||||
s, o = traceCommand("xm setpolicy ACM %s" % (policy))
|
||||
if s != 0:
|
||||
FAIL("Could not load the required policy '%s'.\n"
|
||||
"Start the system without any policy.\n%s" % \
|
||||
(policy, o))
|
||||
|
||||
def ACMPrepareSystem(resources):
|
||||
if isACMEnabled():
|
||||
ACMLoadPolicy()
|
||||
ACMSetPolicy()
|
||||
ACMLabelResources(resources)
|
||||
|
||||
def ACMLabelResources(resources):
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
# A couple of simple tests that test ACM security extensions
|
||||
# for the xm tool. The following xm subcommands are tested:
|
||||
#
|
||||
# - makepolicy
|
||||
# - labels
|
||||
# - rmlabel
|
||||
# - addlabel
|
||||
@@ -28,11 +27,6 @@ testresource = "phy:ram0"
|
||||
if not isACMEnabled():
|
||||
SKIP("Not running this test since ACM not enabled.")
|
||||
|
||||
status, output = traceCommand("xm makepolicy %s" % (testpolicy))
|
||||
if status != 0:
|
||||
FAIL("'xm makepolicy' failed with status %d and output\n%s" %
|
||||
(status,output));
|
||||
|
||||
status, output = traceCommand("xm labels %s" % (testpolicy))
|
||||
if status != 0:
|
||||
FAIL("'xm labels' failed with status %d.\n" % status)
|
||||
|
||||
@@ -12,4 +12,4 @@ vmconfigfile = "/tmp/xm-test.conf"
|
||||
if not isACMEnabled():
|
||||
SKIP("Not running this test since ACM not enabled.")
|
||||
|
||||
ACMLoadPolicy(testpolicy)
|
||||
ACMSetPolicy(testpolicy)
|
||||