--- xen-unstable.hg/tools/python/xen/util/acmpolicy.py | 64 +++++++--- xen-unstable.hg/tools/python/xen/util/security.py | 30 ++++ xen-unstable.hg/tools/python/xen/xm/activatepolicy.py | 27 ++++ xen-unstable.hg/tools/python/xen/xm/resources.py | 1 xen-unstable.hg/tools/python/xen/xm/setpolicy.py | 40 +++++- xen-unstable.hg/tools/security/Makefile | 11 - xen-unstable.hg/tools/security/policies/default-security_policy.xml | 40 ++++++ xen-unstable.hg/tools/security/policies/default-ul-security_policy.xml | 30 ++++ 8 files changed, 211 insertions(+), 32 deletions(-) Index: root/xen-unstable.hg/tools/python/xen/util/acmpolicy.py =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/util/acmpolicy.py +++ root/xen-unstable.hg/tools/python/xen/util/acmpolicy.py @@ -142,6 +142,21 @@ class ACMPolicy(XSPolicy): return xsconstants.XSERR_SUCCESS + def is_default_policy(self): + """ + Determine whether this is the default policy + """ + default = ['SystemManagement'] + if self.policy_get_virtualmachinelabel_names() == default and \ + self.policy_get_bootstrap_vmlabel() == default[0] and \ + self.policy_get_stetypes_types() == default and \ + self.policy_get_stes_of_vmlabel(default[0]) == default and \ + self.policy_get_resourcelabel_names() == [] and \ + self.policy_get_chwall_types() == default and \ + self.get_name() == "DEFAULT": + return True + return False + def update(self, xml_new): """ Update the policy with the new XML. The hypervisor decides @@ -156,27 +171,18 @@ class ACMPolicy(XSPolicy): return -xsconstants.XSERR_XML_PROCESSING, errors vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map() + # An update requires version information in the current # and new policy. The version number of the current policy # must be the same as what is in the FromPolicy/Version node # in the new one and the current policy's name must be the # same as in FromPolicy/PolicyName - - now_vers = acmpol_old.policy_dom_get_hdr_item("Version") - now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName") - req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version") - req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName") - - if now_vers == "" or \ - now_vers != req_oldvers or \ - now_name != req_oldname: - log.info("Policy rejected: %s != %s or %s != %s" % \ - (now_vers,req_oldvers,now_name,req_oldname)) - return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors - - if not self.isVersionUpdate(acmpol_new): - log.info("Policy rejected since new version is not an update.") - return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors + # The default policy when it is set skips this step. + if not acmpol_new.is_default_policy() and \ + not acmpol_old.is_default_policy(): + irc = self.__do_update_version_check(acmpol_new) + if irc != xsconstants.XSERR_SUCCESS: + return irc, errors if self.isloaded(): newvmnames = \ @@ -258,6 +264,29 @@ class ACMPolicy(XSPolicy): self.compile() return rc, errors + + def __do_update_version_check(self, acmpol_new): + acmpol_old = self + + now_vers = acmpol_old.policy_dom_get_hdr_item("Version") + now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName") + req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version") + req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName") + + if now_vers == "" or \ + now_vers != req_oldvers or \ + now_name != req_oldname: + log.info("Policy rejected: %s != %s or %s != %s" % \ + (now_vers,req_oldvers,now_name,req_oldname)) + return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE + + if not self.isVersionUpdate(acmpol_new): + log.info("Policy rejected since new version is not an update.") + return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE + + return xsconstants.XSERR_SUCCESS + + def compareVersions(self, v1, v2): """ Compare two policy versions given their tuples of major and @@ -848,8 +877,7 @@ class ACMPolicy(XSPolicy): if self.isloaded(): return -xsconstants.XSERR_POLICY_LOADED files = [ self.get_filename(".map",""), - self.get_filename(".bin",""), - self.path_from_policy_name(self.get_name())] + self.get_filename(".bin","") ] for f in files: try: os.unlink(f) Index: root/xen-unstable.hg/tools/python/xen/util/security.py =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/util/security.py +++ root/xen-unstable.hg/tools/python/xen/util/security.py @@ -146,7 +146,7 @@ def calc_dom_ssidref_from_info(info): raise VmError("VM label '%s' in wrong format." % seclab) typ, policyname, vmlabel = seclab.split(":") if typ != xsconstants.ACM_POLICY_ID: - raise VmError("Policy type '%s' not supported." % typ) + raise VmError("Policy type '%s' must be changed." % typ) refresh_security_policy() if active_policy != policyname: raise VmError("Active policy '%s' different than " @@ -502,7 +502,7 @@ def hv_chg_policy(bin_pol, del_array, ch rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array) except Exception, e: pass - if (len(errors) > 0): + if len(errors) > 0: rc = -xsconstants.XSERR_HV_OP_FAILED return rc, errors @@ -785,6 +785,24 @@ def res_security_check_xapi(rlabel, rssi return rtnval +def validate_label(label, policyref): + """ + Make sure that this label is part of the currently enforced policy + and that it reference the current policy. + """ + rc = xsconstants.XSERR_SUCCESS + from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance + curpol = XSPolicyAdminInstance().get_loaded_policy() + if not curpol or curpol.get_name() != policyref: + rc = -xsconstants.XSERR_BAD_LABEL + else: + try: + label2ssidref(label, curpol.get_name() , 'res') + except: + rc = -xsconstants.XSERR_BAD_LABEL + return rc + + def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi): """Assign a resource label to a resource @param resource: The name of a resource, i.e., "phy:/dev/hda", or @@ -809,10 +827,16 @@ def set_resource_label_xapi(resource, re return -xsconstants.XSERR_BAD_LABEL_FORMAT otyp, opolicyref, olabel = tmp # Only ACM is supported - if otyp != xsconstants.ACM_POLICY_ID: + if otyp != xsconstants.ACM_POLICY_ID and \ + 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 return set_resource_label(resource, typ, policyref, label, olabel) + def is_resource_in_use(resource): """ Investigate all running domains whether they use this device """ from xen.xend import XendDomain @@ -1228,7 +1252,7 @@ def change_acm_policy(bin_pol, del_array sec_lab, new_seclab = labels if sec_lab != new_seclab: log.info("Updating domain %s to new label '%s'." % \ - (new_seclab, sec_lab)) + (sec_lab, new_seclab)) # This better be working! dominfo.set_security_label(new_seclab, sec_lab, Index: root/xen-unstable.hg/tools/security/policies/default-security_policy.xml =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/security/policies/default-security_policy.xml @@ -0,0 +1,30 @@ + + + + DEFAULT + 1.0 + + + + SystemManagement + + + + + SystemManagement + + + + + + SystemManagement + + SystemManagement + + + + + + + + Index: root/xen-unstable.hg/tools/security/Makefile =================================================================== --- root.orig/xen-unstable.hg/tools/security/Makefile +++ root/xen-unstable.hg/tools/security/Makefile @@ -13,13 +13,6 @@ CFLAGS += $(shell xml2-config --cfla CFLAGS += $(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi ) LDFLAGS += $(shell xml2-config --libs ) # if this does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm -ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_NULL_POLICY) -POLICY=null -endif -ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) -POLICY=chwall_ste -endif - SRCS_TOOL = secpol_tool.c OBJS_TOOL := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_TOOL))) SRCS_XML2BIN = secpol_xml2bin.c secpol_xml2bin.h @@ -41,6 +34,7 @@ ACM_SECGEN_CGIDIR = $(ACM_SECGEN_HTMLDIR ACM_SCHEMA = security_policy.xsd ACM_EXAMPLES = client_v1 test +ACM_DEF_POLICIES = default default-ul ACM_POLICY_SUFFIX = security_policy.xml ifeq ($(ACM_SECURITY),y) @@ -62,6 +56,9 @@ install: all $(ACM_CONFIG_FILE) for i in $(ACM_EXAMPLES); do \ $(INSTALL_DATA) policies/example/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR)/example/; \ done + for i in $(ACM_DEF_POLICIES); do \ + $(INSTALL_DATA) policies/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR); \ + done $(INSTALL_DIR) $(DESTDIR)$(ACM_SCRIPT_DIR) $(INSTALL_PROG) $(ACM_SCRIPTS) $(DESTDIR)$(ACM_SCRIPT_DIR) $(INSTALL_DIR) $(DESTDIR)$(ACM_SECGEN_HTMLDIR) Index: root/xen-unstable.hg/tools/python/xen/xm/activatepolicy.py =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/xm/activatepolicy.py +++ root/xen-unstable.hg/tools/python/xen/xm/activatepolicy.py @@ -23,7 +23,7 @@ import sys from xen.util import xsconstants from xml.dom import minidom from xen.xm.opts import OptionError -from xen.xm import getpolicy +from xen.xm import getpolicy, setpolicy from xen.xm import main as xm_main from xen.xm.main import server @@ -38,6 +38,9 @@ def help(): --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): @@ -56,6 +59,25 @@ def activate_policy(flags): 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.') @@ -69,6 +91,9 @@ def main(argv): 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 Index: root/xen-unstable.hg/tools/python/xen/xm/setpolicy.py =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/xm/setpolicy.py +++ root/xen-unstable.hg/tools/python/xen/xm/setpolicy.py @@ -24,6 +24,7 @@ import struct import sys import string from xen.util import xsconstants +from xen.util.acmpolicy import ACMPolicy from xen.xm.opts import OptionError from xen.util.security import policy_dir_prefix from xen.xm import main as xm_main @@ -40,9 +41,38 @@ def help(): 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 """ -def setpolicy(policytype, policy_name, flags, overwrite): +def create_update_xml(xml): + """ + 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'. + """ + 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) + + 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: @@ -61,6 +91,9 @@ def setpolicy(policytype, policy_name, f except: raise OptionError("Not a valid policy file") + if is_update: + xml = create_update_xml(xml) + try: policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type, xml, @@ -96,18 +129,21 @@ 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 overwrite = True if '--nooverwrite' in argv: overwrite = False - setpolicy(policytype, policy_name, flags, overwrite) + setpolicy(policytype, policy_name, flags, overwrite, is_update) if __name__ == '__main__': try: Index: root/xen-unstable.hg/tools/python/xen/xm/resources.py =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/xm/resources.py +++ root/xen-unstable.hg/tools/python/xen/xm/resources.py @@ -58,7 +58,6 @@ def main (argv): try: filename = security.res_label_filename access_control = dictio.dict_read("resources", filename) - print access_control except: raise OptionError("Resource file not found") Index: root/xen-unstable.hg/tools/security/policies/default-ul-security_policy.xml =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/security/policies/default-ul-security_policy.xml @@ -0,0 +1,41 @@ + + + + DEFAULT-UL + 1.0 + + + + SystemManagement + __UNLABELED__ + + + + + SystemManagement + + + + + + SystemManagement + + SystemManagement + __UNLABELED__ + + + + + + + __UNLABELED__ + + __UNLABELED__ + + + + + + + +