diff options
32 files changed, 1001 insertions, 2860 deletions
diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 index 72932dee93..3e98fadc9c 100644 --- a/docs/man/xm.pod.1 +++ b/docs/man/xm.pod.1 @@ -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,47 +933,39 @@ 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<SETTING A SECURITY POLICY> +B<RESETTING THE SYSTEM'S SECURITY> =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. - - xm setpolicy ACM example.client_v1 +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. -=back + xm resetpolicy -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 +After this command has successfully completed, the system's DEFAULT policy +is enforced. =back -B<CONFIGURING A BOOT SECURITY POLICY> +B<SETTING A 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. +This step sets the system's policy and automatically loads it into Xen +for enforcement. - xm activatepolicy --boot + xm setpolicy ACM example.client_v1 =back diff --git a/tools/python/xen/util/acmpolicy.py b/tools/python/xen/util/acmpolicy.py index 3f247d2a52..13bcda377a 100644 --- a/tools/python/xen/util/acmpolicy.py +++ b/tools/python/xen/util/acmpolicy.py @@ -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 diff --git a/tools/python/xen/util/xsm/acm/acm.py b/tools/python/xen/util/xsm/acm/acm.py index 47e9ce586d..d8f4be4314 100644 --- a/tools/python/xen/util/xsm/acm/acm.py +++ b/tools/python/xen/util/xsm/acm/acm.py @@ -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() diff --git a/tools/python/xen/util/xsm/dummy/dummy.py b/tools/python/xen/util/xsm/dummy/dummy.py index 42a41b36c9..7a07e906d0 100644 --- a/tools/python/xen/util/xsm/dummy/dummy.py +++ b/tools/python/xen/util/xsm/dummy/dummy.py @@ -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.") diff --git a/tools/python/xen/util/xsm/flask/flask.py b/tools/python/xen/util/xsm/flask/flask.py index a0f931b364..933f0898c8 100644 --- a/tools/python/xen/util/xsm/flask/flask.py +++ b/tools/python/xen/util/xsm/flask/flask.py @@ -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. """ diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index d43355d2ba..bdd8e6dff6 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -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)): diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index eaee766cf0..4558a9cec6 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -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: diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py index 2ca9f30096..d762bc8c4a 100644 --- a/tools/python/xen/xend/XendXSPolicyAdmin.py +++ b/tools/python/xen/xend/XendXSPolicyAdmin.py @@ -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 """ diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py index 91eb21632d..6aad3df9bd 100644 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ b/tools/python/xen/xend/server/XMLRPCServer.py @@ -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 diff --git a/tools/python/xen/xm/activatepolicy.py b/tools/python/xen/xm/activatepolicy.py deleted file mode 100644 index 270b510eac..0000000000 --- a/tools/python/xen/xm/activatepolicy.py +++ /dev/null @@ -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) diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py index 0ba3b925ff..fcc3516a51 100644 --- a/tools/python/xen/xm/addlabel.py +++ b/tools/python/xen/xm/addlabel.py @@ -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.') + 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: + msg = xsconstants.xserr2string(-rc) + raise security.XSMError("An error occurred relabeling " + "the domain: %s" % msg) else: - ssidref = int(rc) - if ssidref != 0: - print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %\ - (domainname,label,ssidref) + 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: - print "Set the label of dormant domain '%s' to '%s'." % \ - (domainname,label) + 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 diff --git a/tools/python/xen/xm/cfgbootpolicy.py b/tools/python/xen/xm/cfgbootpolicy.py deleted file mode 100644 index 2436f2501b..0000000000 --- a/tools/python/xen/xm/cfgbootpolicy.py +++ /dev/null @@ -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) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index b1ec86afa7..e666cb2e85 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -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): diff --git a/tools/python/xen/xm/dry-run.py b/tools/python/xen/xm/dry-run.py index a0b2c84c03..fd62131a52 100644 --- a/tools/python/xen/xm/dry-run.py +++ b/tools/python/xen/xm/dry-run.py @@ -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)" diff --git a/tools/python/xen/xm/getlabel.py b/tools/python/xen/xm/getlabel.py index d54e54f25b..45c4a7aff4 100644 --- a/tools/python/xen/xm/getlabel.py +++ b/tools/python/xen/xm/getlabel.py @@ -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) - diff --git a/tools/python/xen/xm/getpolicy.py b/tools/python/xen/xm/getpolicy.py index 3f5d6d3a24..a96dde06db 100644 --- a/tools/python/xen/xm/getpolicy.py +++ b/tools/python/xen/xm/getpolicy.py @@ -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'] + +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: + acmpol = ACMPolicy(xml=xml) + + display_policy_info(acmpol, + xsconstants.ACM_POLICY_ID, + policystate['xs_ref'], + policystate['version'], + int(policystate['flags']), + dumpxml, + xml) else: - xml = policystate['repr'] + xstype = server.xend.security.get_xstype() + display_security_subsystems(xstype) + + xml, flags = server.xend.security.get_policy() acmpol = None - if xml: - acmpol = ACMPolicy(xml=xml) - print "Policy installed on the system:" + 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: - 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: - xml = policystate['repr'] - if xml: - dom = minidom.parseString(xml.encode("utf-8")) - print "%s" % dom.toprettyxml(indent=" ",newl="\n") + 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 diff --git a/tools/python/xen/xm/labels.py b/tools/python/xen/xm/labels.py index b8f676d70a..0ad0d9b996 100644 --- a/tools/python/xen/xm/labels.py +++ b/tools/python/xen/xm/labels.py @@ -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 + "\'") - - try: - labels = list_labels(policy, condition) - labels.sort() - for label in labels: - print label + labels = server.xend.security.list_labels(policy, ptype) + 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() diff --git a/tools/python/xen/xm/loadpolicy.py b/tools/python/xen/xm/loadpolicy.py deleted file mode 100644 index 4104a6eec5..0000000000 --- a/tools/python/xen/xm/loadpolicy.py +++ /dev/null @@ -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) - diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5528395e03..78958ce9da 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -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: diff --git a/tools/python/xen/xm/makepolicy.py b/tools/python/xen/xm/makepolicy.py deleted file mode 100644 index 2a208b0a68..0000000000 --- a/tools/python/xen/xm/makepolicy.py +++ /dev/null @@ -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) diff --git a/tools/python/xen/xm/resetpolicy.py b/tools/python/xen/xm/resetpolicy.py new file mode 100644 index 0000000000..bc37760d2c --- /dev/null +++ b/tools/python/xen/xm/resetpolicy.py @@ -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) diff --git a/tools/python/xen/xm/resources.py b/tools/python/xen/xm/resources.py index 51e1c48858..cc8a6cc49c 100644 --- a/tools/python/xen/xm/resources.py +++ b/tools/python/xen/xm/resources.py @@ -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) diff --git a/tools/python/xen/xm/rmlabel.py b/tools/python/xen/xm/rmlabel.py index a31086e3c0..745350bf17 100644 --- a/tools/python/xen/xm/rmlabel.py +++ b/tools/python/xen/xm/rmlabel.py @@ -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: diff --git a/tools/python/xen/xm/setpolicy.py b/tools/python/xen/xm/setpolicy.py index 1901a65ca1..e450b955ce 100644 --- a/tools/python/xen/xm/setpolicy.py +++ b/tools/python/xen/xm/setpolicy.py @@ -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) - - 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: + 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 + + +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") - - if is_update: - xml = create_update_xml(xml) - - 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) + raise OptionError("Could not read policy file from current" + " directory or '%s'." % policy_dir_prefix) + + 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 != 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: diff --git a/tools/security/Makefile b/tools/security/Makefile index 4a193596d2..f79258b89b 100644 --- a/tools/security/Makefile +++ b/tools/security/Makefile @@ -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 $^ $@ diff --git a/tools/security/policies/example/client_v1-security_policy.xml b/tools/security/policies/example/client_v1-security_policy.xml index 669f0696c5..2b3a6f098a 100644 --- a/tools/security/policies/example/client_v1-security_policy.xml +++ b/tools/security/policies/example/client_v1-security_policy.xml @@ -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 ... --> diff --git a/tools/security/policies/example/ste/client_v1-security_policy.xml b/tools/security/policies/example/ste/client_v1-security_policy.xml deleted file mode 100644 index dcdc1c05d9..0000000000 --- a/tools/security/policies/example/ste/client_v1-security_policy.xml +++ /dev/null @@ -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> - diff --git a/tools/security/secpol_xml2bin.c b/tools/security/secpol_xml2bin.c deleted file mode 100644 index 0fbe8efcbd..0000000000 --- a/tools/security/secpol_xml2bin.c +++ /dev/null @@ -1,1457 +0,0 @@ -/**************************************************************** - * secpol_xml2bin.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: Reiner Sailer <sailer@us.ibm.com> - * - * Maintained: - * Reiner Sailer <sailer@us.ibm.com> - * Ray Valdez <rvaldez@us.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. - * - * sHype policy translation tool. This tool takes an XML - * policy specification as input and produces a binary - * policy file that can be loaded into Xen through the - * ACM operations (xensec_tool loadpolicy) interface or at - * boot time (grub module parameter) - * - * indent -i4 -kr -nut - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libgen.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <libxml/xmlschemas.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xmlreader.h> -#include <stdint.h> -#include <xen/xsm/acm.h> - -#include "secpol_xml2bin.h" - -#define DEBUG 0 - -#define NULL_LABEL_NAME "__NULL_LABEL__" - -#define ROUND8(x) ((x + 7) & ~7) - -/* primary / secondary policy component setting */ -enum policycomponent { CHWALL, STE, NULLPOLICY } - primary = NULLPOLICY, secondary = NULLPOLICY; - -/* general list element for ste and chwall type queues */ -struct type_entry { - TAILQ_ENTRY(type_entry) entries; - char *name; /* name of type from xml file */ - type_t mapping; /* type mapping into 16bit */ -}; - -TAILQ_HEAD(tailhead, type_entry) ste_head, chwall_head; - -/* general list element for all label queues */ -enum label_type { VM, RES, ANY }; -struct ssid_entry { - TAILQ_ENTRY(ssid_entry) entries; - char *name; /* label name */ - enum label_type type; /* type: VM / RESOURCE LABEL */ - u_int32_t num; /* ssid or referenced ssid */ - int is_ref; /* if this entry references earlier ssid number */ - unsigned char *row; /* index of types (if not a reference) */ -}; - -TAILQ_HEAD(tailhead_ssid, ssid_entry) ste_ssid_head, chwall_ssid_head, - conflictsets_head; -struct ssid_entry *current_chwall_ssid_p = NULL; -struct ssid_entry *current_ste_ssid_p = NULL; -struct ssid_entry *current_conflictset_p = NULL; - -/* which label to assign to dom0 during boot */ -char *bootstrap_label; - -u_int32_t max_ste_ssids = 0; -u_int32_t max_chwall_ssids = 0; -u_int32_t max_chwall_labels = 0; -u_int32_t max_ste_labels = 0; -u_int32_t max_conflictsets = 0; - -char *current_ssid_name; /* store name until structure is allocated */ -char *current_conflictset_name; /* store name until structure is allocated */ - -/* dynamic list of type mappings for STE */ -u_int32_t max_ste_types = 0; - -/* dynamic list of type mappings for CHWALL */ -u_int32_t max_chwall_types = 0; - -/* dynamic list of conflict sets */ -int max_conflict_set = 0; - -/* which policies are defined */ -int have_ste = 0; -int have_chwall = 0; - -/* input/output file names */ -char *policy_filename = NULL, - *binary_filename = NULL, - *mapping_filename = NULL, *schema_filename = NULL; - -char *policy_reference_name = NULL; - -char *policy_version_string = NULL; - -void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state); - -void usage(char *prg) -{ - printf( - "Usage: %s [OPTIONS] POLICYNAME\n" - "POLICYNAME is the directory name within the policy directory\n" - "that contains the policy files. The default policy directory\n" - "is '%s' (see the '-d' option below to change it)\n" - "The policy files contained in the POLICYNAME directory must be named:\n" - "\tPOLICYNAME-security_policy.xml\n" - "\tPOLICYNAME-security_label_template.xml\n\n" - "OPTIONS:\n" - "\t-d POLICYDIR\n" - "\t\tUse POLICYDIR as the policy directory. This directory must \n" - "\t\tcontain the policy schema file 'security_policy.xsd'\n", - prg, POLICY_DIR); - exit(EXIT_FAILURE); -} - - -/***************** policy-related parsing *********************/ - -char *type_by_mapping(struct tailhead *head, u_int32_t mapping) -{ - struct type_entry *np; - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) - if (np->mapping == mapping) - return np->name; - return NULL; -} - - -struct type_entry *lookup(struct tailhead *head, char *name) -{ - struct type_entry *np; - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) - if (!(strcmp(np->name, name))) - return np; - return NULL; -} - -/* enforces single-entry lists */ -int add_entry(struct tailhead *head, char *name, type_t mapping) -{ - struct type_entry *e; - if (lookup(head, name)) { - printf("Error: Type >%s< defined more than once.\n", name); - return -EFAULT; /* already in the list */ - } - if (!(e = malloc(sizeof(struct type_entry)))) - return -ENOMEM; - - e->name = name; - e->mapping = mapping; - TAILQ_INSERT_TAIL(head, e, entries); - return 0; -} - -int totoken(char *tok) -{ - int i; - for (i = 0; token[i] != NULL; i++) - if (!strcmp(token[i], tok)) - return i; - return -EFAULT; -} - -/* conflictsets use the same data structure as ssids; since - * they are similar in structure (set of types) - */ -int init_next_conflictset(void) -{ - struct ssid_entry *conflictset = malloc(sizeof(struct ssid_entry)); - - if (!conflictset) - return -ENOMEM; - - conflictset->name = current_conflictset_name; - conflictset->num = max_conflictsets++; - conflictset->is_ref = 0; /* n/a for conflictsets */ - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the conflictset - */ - conflictset->row = malloc(max_chwall_types); - if (!conflictset->row) - return -ENOMEM; - - memset(conflictset->row, 0, max_chwall_types); - TAILQ_INSERT_TAIL(&conflictsets_head, conflictset, entries); - current_conflictset_p = conflictset; - return 0; -} - -int register_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) -{ - xmlChar *text; - struct type_entry *e; - - - text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!text) { - printf("Error reading type name!\n"); - return -EFAULT; - } - - switch (state) { - case XML2BIN_stetype_S: - if (add_entry(&ste_head, (char *) text, max_ste_types)) { - xmlFree(text); - return -EFAULT; - } - max_ste_types++; - break; - - case XML2BIN_chwalltype_S: - if (add_entry(&chwall_head, (char *) text, max_chwall_types)) { - xmlFree(text); - return -EFAULT; - } - max_chwall_types++; - break; - - case XML2BIN_conflictsettype_S: - /* a) search the type in the chwall_type list */ - e = lookup(&chwall_head, (char *) text); - if (e == NULL) { - printf("CS type >%s< not a CHWALL type.\n", text); - xmlFree(text); - return -EFAULT; - } - /* b) add type entry to the current cs set */ - if (current_conflictset_p->row[e->mapping]) { - printf - ("ERROR: Double entry of type >%s< in conflict set %d.\n", - text, current_conflictset_p->num); - xmlFree(text); - return -EFAULT; - } - current_conflictset_p->row[e->mapping] = 1; - break; - - default: - printf("Incorrect type environment (state = %lx, text = %s).\n", - state, text); - xmlFree(text); - return -EFAULT; - } - return 0; -} - -void set_component_type(xmlNode * cur_node, enum policycomponent pc) -{ - xmlChar *order; - - if ((order = - xmlGetProp(cur_node, (xmlChar *) PRIMARY_COMPONENT_ATTR_NAME))) { - if (strcmp((char *) order, PRIMARY_COMPONENT)) { - printf("ERROR: Illegal attribut value >order=%s<.\n", - (char *) order); - xmlFree(order); - exit(EXIT_FAILURE); - } - if (primary != NULLPOLICY) { - printf("ERROR: Primary Policy Component set twice!\n"); - exit(EXIT_FAILURE); - } - primary = pc; - xmlFree(order); - } -} - -void walk_policy(xmlNode * start, xmlDocPtr doc, unsigned long state) -{ - xmlNode *cur_node = NULL; - int code; - - for (cur_node = start; cur_node; cur_node = cur_node->next) { - if ((code = totoken((char *) cur_node->name)) < 0) { - printf("Unknown token: >%s<. Aborting.\n", cur_node->name); - exit(EXIT_FAILURE); - } - switch (code) { /* adjust state to new state */ - case XML2BIN_SECPOL: - case XML2BIN_STETYPES: - case XML2BIN_CHWALLTYPES: - case XML2BIN_CONFLICTSETS: - case XML2BIN_POLICYHEADER: - case XML2BIN_FROMPOLICY: - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_POLICYNAME: /* get policy reference name .... */ - if (state != XML2BIN_PN_S && - state != XML2BIN_PN_frompolicy_S) { - printf("ERROR: >Url< >%s< out of context.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1)); - exit(EXIT_FAILURE); - } - if (state == XML2BIN_PN_S) { - policy_reference_name = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!policy_reference_name) { - printf("ERROR: empty >policy reference name (Url)<!\n"); - exit(EXIT_FAILURE); - } else - printf("Policy Reference name (Url): %s\n", - policy_reference_name); - } - break; - - case XML2BIN_VERSION: /* get policy version number .... */ - if (state != XML2BIN_PN_S && - state != XML2BIN_PN_frompolicy_S) { - printf("ERROR: >Url< >%s< out of context.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1)); - exit(EXIT_FAILURE); - } - if (state == XML2BIN_PN_S) { - policy_version_string = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!policy_version_string) { - printf("ERROR: empty >policy version string <!\n"); - exit(EXIT_FAILURE); - } else - printf("Policy version string: %s\n", - policy_version_string); - } - break; - - case XML2BIN_STE: - if (WRITTEN_AGAINST_ACM_STE_VERSION != ACM_STE_VERSION) { - printf - ("ERROR: This program was written against another STE version.\n"); - exit(EXIT_FAILURE); - } - have_ste = 1; - set_component_type(cur_node, STE); - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CHWALL: - if (WRITTEN_AGAINST_ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) { - printf - ("ERROR: This program was written against another CHWALL version.\n"); - exit(EXIT_FAILURE); - } - have_chwall = 1; - set_component_type(cur_node, CHWALL); - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CSTYPE: - current_conflictset_name = - (char *) xmlGetProp(cur_node, (xmlChar *) "name"); - if (!current_conflictset_name) - current_conflictset_name = ""; - - if (init_next_conflictset()) { - printf - ("ERROR: creating new conflictset structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_TYPE: - if (register_type(cur_node, doc, state)) - exit(EXIT_FAILURE); - /* type leaf */ - break; - - case XML2BIN_LABELTEMPLATE: /* handle in second pass */ - case XML2BIN_TEXT: - case XML2BIN_COMMENT: - case XML2BIN_DATE: - case XML2BIN_REFERENCE: - case XML2BIN_NSURL: /* for future use: where to find global label / type name mappings */ - case XML2BIN_URL: /* for future use: where to find policy */ - /* leaf - nothing to do */ - break; - - default: - printf("Unkonwn token Error (%d) in Policy\n", code); - exit(EXIT_FAILURE); - } - - } - return; -} - -void init_type_mapping(void) -{ - printf("Creating ssid mappings ...\n"); - - /* initialize the ste and chwall type lists */ - TAILQ_INIT(&ste_head); - TAILQ_INIT(&chwall_head); - TAILQ_INIT(&conflictsets_head); -} - -void post_type_mapping(void) -{ - struct type_entry *te; - struct ssid_entry *se; - int i; - - /* determine primary/secondary policy component orders */ - if ((primary == NULLPOLICY) && have_chwall) - primary = CHWALL; /* default if not set */ - else if ((primary == NULLPOLICY) && have_ste) - primary = STE; - - switch (primary) { - - case CHWALL: - if (have_ste) - secondary = STE; - /* else default = NULLPOLICY */ - break; - - case STE: - if (have_chwall) - secondary = CHWALL; - /* else default = NULLPOLICY */ - break; - - default: - /* NULL/NULL policy */ - break; - } - - if (!DEBUG) - return; - - /* print queues */ - if (have_ste) { - printf("STE-Type queue (%s):\n", - (primary == STE) ? "PRIMARY" : "SECONDARY"); - for (te = ste_head.tqh_first; te != NULL; - te = te->entries.tqe_next) - printf("name=%22s, map=%x\n", te->name, te->mapping); - } - if (have_chwall) { - printf("CHWALL-Type queue (%s):\n", - (primary == CHWALL) ? "PRIMARY" : "SECONDARY"); - for (te = chwall_head.tqh_first; te != NULL; - te = te->entries.tqe_next) - printf("name=%s, map=%x\n", te->name, te->mapping); - - printf("Conflictset queue (max=%d):\n", max_conflictsets); - for (se = conflictsets_head.tqh_first; se != NULL; - se = se->entries.tqe_next) { - printf("conflictset name >%s<\n", - se->name ? se->name : "NONAME"); - for (i = 0; i < max_chwall_types; i++) - if (se->row[i]) - printf("#%x ", i); - printf("\n"); - } - } -} - - -/***************** template-related parsing *********************/ - -/* add default ssid at head of ssid queues */ -int init_ssid_queues(void) -{ - struct ssid_entry *default_ssid_chwall, *default_ssid_ste; - - default_ssid_chwall = malloc(sizeof(struct ssid_entry)); - default_ssid_ste = malloc(sizeof(struct ssid_entry)); - - if ((!default_ssid_chwall) || (!default_ssid_ste)) - return -ENOMEM; - - /* default chwall ssid */ - default_ssid_chwall->name = NULL_LABEL_NAME; - default_ssid_chwall->num = max_chwall_ssids++; - default_ssid_chwall->is_ref = 0; - default_ssid_chwall->type = ANY; - - default_ssid_chwall->row = malloc(max_chwall_types); - - if (!default_ssid_chwall->row) - return -ENOMEM; - - memset(default_ssid_chwall->row, 0, max_chwall_types); - - TAILQ_INSERT_TAIL(&chwall_ssid_head, default_ssid_chwall, entries); - current_chwall_ssid_p = default_ssid_chwall; - max_chwall_labels++; - - /* default ste ssid */ - default_ssid_ste->name = NULL_LABEL_NAME; - default_ssid_ste->num = max_ste_ssids++; - default_ssid_ste->is_ref = 0; - default_ssid_ste->type = ANY; - - default_ssid_ste->row = malloc(max_ste_types); - - if (!default_ssid_ste->row) - return -ENOMEM; - - memset(default_ssid_ste->row, 0, max_ste_types); - - TAILQ_INSERT_TAIL(&ste_ssid_head, default_ssid_ste, entries); - current_ste_ssid_p = default_ssid_ste; - max_ste_labels++; - return 0; -} - -int init_next_chwall_ssid(unsigned long state) -{ - struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); - - if (!ssid) - return -ENOMEM; - - ssid->name = current_ssid_name; - ssid->num = max_chwall_ssids++; - ssid->is_ref = 0; - - if (state & (1 << XML2BIN_VM)) - ssid->type = VM; - else - ssid->type = RES; - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the ssid - */ - ssid->row = malloc(max_chwall_types); - if (!ssid->row) - return -ENOMEM; - - memset(ssid->row, 0, max_chwall_types); - TAILQ_INSERT_TAIL(&chwall_ssid_head, ssid, entries); - current_chwall_ssid_p = ssid; - max_chwall_labels++; - return 0; -} - -int init_next_ste_ssid(unsigned long state) -{ - struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); - - if (!ssid) - return -ENOMEM; - - ssid->name = current_ssid_name; - ssid->num = max_ste_ssids++; - ssid->is_ref = 0; - - if (state & (1 << XML2BIN_VM)) - ssid->type = VM; - else - ssid->type = RES; - - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the ssid - */ - ssid->row = malloc(max_ste_types); - if (!ssid->row) - return -ENOMEM; - - memset(ssid->row, 0, max_ste_types); - TAILQ_INSERT_TAIL(&ste_ssid_head, ssid, entries); - current_ste_ssid_p = ssid; - max_ste_labels++; - - return 0; -} - - -/* adds a type to the current ssid */ -int add_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) -{ - xmlChar *text; - struct type_entry *e; - - text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!text) { - printf("Error reading type name!\n"); - return -EFAULT; - } - /* same for all: 1. lookup type mapping, 2. mark type in ssid */ - switch (state) { - case XML2BIN_VM_STE_S: - case XML2BIN_RES_STE_S: - /* lookup the type mapping and include the type mapping into the array */ - if (!(e = lookup(&ste_head, (char *) text))) { - printf("ERROR: unknown VM STE type >%s<.\n", text); - exit(EXIT_FAILURE); - } - if (current_ste_ssid_p->row[e->mapping]) - printf("Warning: double entry of VM STE type >%s<.\n", text); - - current_ste_ssid_p->row[e->mapping] = 1; - break; - - case XML2BIN_VM_CHWALL_S: - /* lookup the type mapping and include the type mapping into the array */ - if (!(e = lookup(&chwall_head, (char *) text))) { - printf("ERROR: unknown VM CHWALL type >%s<.\n", text); - exit(EXIT_FAILURE); - } - if (current_chwall_ssid_p->row[e->mapping]) - printf("Warning: double entry of VM CHWALL type >%s<.\n", - text); - - current_chwall_ssid_p->row[e->mapping] = 1; - break; - - default: - printf("Incorrect type environment (state = %lx, text = %s).\n", - state, text); - xmlFree(text); - return -EFAULT; - } - return 0; -} - -void set_bootstrap_label(xmlNode * cur_node) -{ - xmlChar *order; - - if ((order = - xmlGetProp(cur_node, (xmlChar *) BOOTSTRAP_LABEL_ATTR_NAME))) - bootstrap_label = (char *) order; - else { - printf("ERROR: No bootstrap label defined!\n"); - exit(EXIT_FAILURE); - } -} - -void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state) -{ - xmlNode *cur_node = NULL; - int code; - - for (cur_node = start; cur_node; cur_node = cur_node->next) { - if ((code = totoken((char *) cur_node->name)) < 0) { - printf("Unkonwn token: >%s<. Aborting.\n", cur_node->name); - exit(EXIT_FAILURE); - } - switch (code) { /* adjust state to new state */ - case XML2BIN_SUBJECTS: - set_bootstrap_label(cur_node); - /* fall through */ - case XML2BIN_SECPOL: - case XML2BIN_LABELTEMPLATE: - case XML2BIN_VM: - case XML2BIN_RES: - case XML2BIN_OBJECTS: - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_STETYPES: - /* create new ssid entry to use and point current to it */ - if (init_next_ste_ssid(state)) { - printf("ERROR: creating new ste ssid structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CHWALLTYPES: - /* create new ssid entry to use and point current to it */ - if (init_next_chwall_ssid(state)) { - printf - ("ERROR: creating new chwall ssid structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_TYPE: - /* add type to current ssid */ - if (add_type(cur_node, doc, state)) - exit(EXIT_FAILURE); - break; - - case XML2BIN_NAME: - if ((state == XML2BIN_VM_S) || (state == XML2BIN_RES_S)) { - current_ssid_name = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, - 1); - if (!current_ssid_name) { - printf("ERROR: empty >vm/res name<!\n"); - exit(EXIT_FAILURE); - } - } else { - printf - ("ERROR: >name< >%s< out of context (state = 0x%lx.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1), - state); - exit(EXIT_FAILURE); - } - break; - - case XML2BIN_TEXT: - case XML2BIN_COMMENT: - case XML2BIN_POLICYHEADER: - case XML2BIN_STE: - case XML2BIN_CHWALL: - break; - - default: - printf("Unkonwn token Error (%d) in Label Template\n", code); - exit(EXIT_FAILURE); - } - } - return; -} - -/* - * will go away as soon as we have non-static bootstrap ssidref for dom0 - */ -void fixup_bootstrap_label(struct tailhead_ssid *head, - u_int32_t max_types, u_int32_t * max_ssids) -{ - struct ssid_entry *np; - int i; - - /* should not happen if xml / xsd checks work */ - if (!bootstrap_label) { - printf("ERROR: No bootstrap label defined.\n"); - exit(EXIT_FAILURE); - } - - /* search bootstrap_label */ - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) { - if (!strcmp(np->name, bootstrap_label)) { - break; - } - } - - if (!np) { - /* bootstrap label not found */ - printf("ERROR: Bootstrap label >%s< not found.\n", - bootstrap_label); - exit(EXIT_FAILURE); - } - - /* move this entry ahead in the list right after the default entry so it - * receives ssidref 1/1 */ - TAILQ_REMOVE(head, np, entries); - TAILQ_INSERT_AFTER(head, head->tqh_first, np, entries); - - /* renumber the ssids (we could also just switch places with 1st element) */ - for (np = head->tqh_first, i = 0; np != NULL; - np = np->entries.tqe_next, i++) - np->num = i; - -} - -void init_label_mapping(void) -{ - - printf("Creating label mappings ...\n"); - /* initialize the ste and chwall type lists */ - TAILQ_INIT(&chwall_ssid_head); - TAILQ_INIT(&ste_ssid_head); - - /* init with default ssids */ - if (init_ssid_queues()) { - printf("ERROR adding default ssids.\n"); - exit(EXIT_FAILURE); - } -} - -void post_label_mapping(void) -{ - struct ssid_entry *np; - int i; - - /* - * now sort bootstrap label to the head of the list - * (for now), dom0 assumes its label in the first - * defined ssidref (1/1). 0/0 is the default non-Label - */ - if (have_chwall) - fixup_bootstrap_label(&chwall_ssid_head, max_chwall_types, - &max_chwall_ssids); - if (have_ste) - fixup_bootstrap_label(&ste_ssid_head, max_ste_types, - &max_ste_ssids); - - if (!DEBUG) - return; - - /* print queues */ - if (have_chwall) { - printf("CHWALL SSID queue (max ssidrefs=%d):\n", max_chwall_ssids); - np = NULL; - for (np = chwall_ssid_head.tqh_first; np != NULL; - np = np->entries.tqe_next) { - printf("SSID #%02u (Label=%s)\n", np->num, np->name); - if (np->is_ref) - printf("REFERENCE"); - else - for (i = 0; i < max_chwall_types; i++) - if (np->row[i]) - printf("#%02d ", i); - printf("\n\n"); - } - } - if (have_ste) { - printf("STE SSID queue (max ssidrefs=%d):\n", max_ste_ssids); - np = NULL; - for (np = ste_ssid_head.tqh_first; np != NULL; - np = np->entries.tqe_next) { - printf("SSID #%02u (Label=%s)\n", np->num, np->name); - if (np->is_ref) - printf("REFERENCE"); - else - for (i = 0; i < max_ste_types; i++) - if (np->row[i]) - printf("#%02d ", i); - printf("\n\n"); - } - } -} - -void create_mappings(xmlDocPtr doc) -{ - xmlNode *doc_root_node = xmlDocGetRootElement(doc); - - /* walk the XML policy tree and fill in types and labels */ - init_type_mapping(); - walk_policy(doc_root_node, doc, XML2BIN_NULL); /* first pass: types */ - post_type_mapping(); - init_label_mapping(); - walk_labels(doc_root_node, doc, XML2BIN_NULL); /* second pass: labels */ - post_label_mapping(); -} - -/***************** writing the binary policy *********************/ - -/* - * the mapping file is ascii-based since it will likely be used from - * within scripts (using awk, grep, etc.); - * - * We print from high-level to low-level information so that with one - * pass, any symbol can be resolved (e.g. Label -> types) - */ -int write_mapping(char *filename) -{ - - struct ssid_entry *e; - struct type_entry *t; - int i; - FILE *file; - - if ((file = fopen(filename, "w")) == NULL) - return -EIO; - - fprintf(file, "POLICYREFERENCENAME %s\n", policy_reference_name); - fprintf(file, "MAGIC %08x\n", ACM_MAGIC); - fprintf(file, "POLICY FILE %s\n", policy_filename); - fprintf(file, "BINARY FILE %s\n", binary_filename); - if (have_chwall) { - fprintf(file, "MAX-CHWALL-TYPES %08x\n", max_chwall_types); - fprintf(file, "MAX-CHWALL-SSIDS %08x\n", max_chwall_ssids); - fprintf(file, "MAX-CHWALL-LABELS %08x\n", max_chwall_labels); - } - if (have_ste) { - fprintf(file, "MAX-STE-TYPES %08x\n", max_ste_types); - fprintf(file, "MAX-STE-SSIDS %08x\n", max_ste_ssids); - fprintf(file, "MAX-STE-LABELS %08x\n", max_ste_labels); - } - fprintf(file, "\n"); - - /* primary / secondary order for combined ssid synthesis/analysis - * if no primary is named, then chwall is primary */ - switch (primary) { - case CHWALL: - fprintf(file, "PRIMARY CHWALL\n"); - break; - - case STE: - fprintf(file, "PRIMARY STE\n"); - break; - - default: - fprintf(file, "PRIMARY NULL\n"); - break; - } - - switch (secondary) { - case CHWALL: - fprintf(file, "SECONDARY CHWALL\n"); - break; - - case STE: - fprintf(file, "SECONDARY STE\n"); - break; - - default: - fprintf(file, "SECONDARY NULL\n"); - break; - } - fprintf(file, "\n"); - - /* first labels to ssid mappings */ - if (have_chwall) { - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - fprintf(file, "LABEL->SSID %s CHWALL %-25s %8x\n", - (e->type == - VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), - e->name, e->num); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (e = ste_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - fprintf(file, "LABEL->SSID %s STE %-25s %8x\n", - (e->type == - VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), - e->name, e->num); - } - fprintf(file, "\n"); - } - - /* second ssid to type mappings */ - if (have_chwall) { - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - fprintf(file, "SSID->TYPE CHWALL %08x", e->num); - - for (i = 0; i < max_chwall_types; i++) - if (e->row[i]) - fprintf(file, " %s", type_by_mapping(&chwall_head, i)); - - fprintf(file, "\n"); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (e = ste_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - fprintf(file, "SSID->TYPE STE %08x", e->num); - - for (i = 0; i < max_ste_types; i++) - if (e->row[i]) - fprintf(file, " %s", type_by_mapping(&ste_head, i)); - - fprintf(file, "\n"); - } - fprintf(file, "\n"); - } - /* third type mappings */ - if (have_chwall) { - for (t = chwall_head.tqh_first; t != NULL; t = t->entries.tqe_next) { - fprintf(file, "TYPE CHWALL %-25s %8x\n", - t->name, t->mapping); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (t = ste_head.tqh_first; t != NULL; t = t->entries.tqe_next) { - fprintf(file, "TYPE STE %-25s %8x\n", - t->name, t->mapping); - } - fprintf(file, "\n"); - } - fclose(file); - return 0; -} - - -unsigned char *write_policy_reference_binary(u_int32_t * len_pr) -{ - unsigned char *buf, *ptr; - struct acm_policy_reference_buffer *pr_header; - u_int32_t len; - u_int32_t name_len; - - if (policy_reference_name == NULL) { - printf("ERROR: No policy reference name found.\n"); - exit(EXIT_FAILURE); - } - name_len = strlen(policy_reference_name) + 1; /* strend '\0' */ - len = sizeof(struct acm_policy_reference_buffer) + name_len; - len = (len + 7) & ~7; /* Alignment. */ - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf - ("ERROR: out of memory allocating label reference buffer.\n"); - exit(EXIT_FAILURE); - } - memset (buf, 0, len); - pr_header = (struct acm_policy_reference_buffer *) buf; - pr_header->len = htonl(name_len); - ptr += sizeof(struct acm_policy_reference_buffer); - strcpy((char *) ptr, policy_reference_name); - - (*len_pr) = len; - return buf; -} - - -unsigned char *write_chwall_binary(u_int32_t * len_chwall) -{ - unsigned char *buf, *ptr; - struct acm_chwall_policy_buffer *chwall_header; - u_int32_t len; - struct ssid_entry *e; - int i; - - if (!have_chwall) - return NULL; - - len = sizeof(struct acm_chwall_policy_buffer) + - sizeof(type_t) * max_chwall_types * max_chwall_ssids + - sizeof(type_t) * max_chwall_types * max_conflictsets; - - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf("ERROR: out of memory allocating chwall buffer.\n"); - exit(EXIT_FAILURE); - } - /* chwall has 3 parts : header, types, conflictsets */ - - chwall_header = (struct acm_chwall_policy_buffer *) buf; - chwall_header->chwall_max_types = htonl(max_chwall_types); - chwall_header->chwall_max_ssidrefs = htonl(max_chwall_ssids); - chwall_header->policy_code = htonl(ACM_CHINESE_WALL_POLICY); - chwall_header->policy_version = htonl(ACM_CHWALL_VERSION); - chwall_header->chwall_ssid_offset = - htonl(sizeof(struct acm_chwall_policy_buffer)); - chwall_header->chwall_max_conflictsets = htonl(max_conflictsets); - chwall_header->chwall_conflict_sets_offset = - htonl(ntohl(chwall_header->chwall_ssid_offset) + - sizeof(domaintype_t) * max_chwall_ssids * max_chwall_types); - chwall_header->chwall_running_types_offset = 0; - chwall_header->chwall_conflict_aggregate_offset = 0; - ptr += sizeof(struct acm_chwall_policy_buffer); - - /* types */ - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - for (i = 0; i < max_chwall_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_chwall_types; - } - - /* conflictsets */ - for (e = conflictsets_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - for (i = 0; i < max_chwall_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_chwall_types; - } - - if ((ptr - buf) != len) { - printf("ERROR: wrong lengths in %s.\n", __func__); - exit(EXIT_FAILURE); - } - - (*len_chwall) = len; - return buf; -} - -unsigned char *write_ste_binary(u_int32_t * len_ste) -{ - unsigned char *buf, *ptr; - struct acm_ste_policy_buffer *ste_header; - struct ssid_entry *e; - u_int32_t len; - int i; - - if (!have_ste) - return NULL; - - len = sizeof(struct acm_ste_policy_buffer) + - sizeof(type_t) * max_ste_types * max_ste_ssids; - - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf("ERROR: out of memory allocating chwall buffer.\n"); - exit(EXIT_FAILURE); - } - - /* fill buffer */ - ste_header = (struct acm_ste_policy_buffer *) buf; - ste_header->policy_version = htonl(ACM_STE_VERSION); - ste_header->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - ste_header->ste_max_types = htonl(max_ste_types); - ste_header->ste_max_ssidrefs = htonl(max_ste_ssids); - ste_header->ste_ssid_offset = - htonl(sizeof(struct acm_ste_policy_buffer)); - - ptr += sizeof(struct acm_ste_policy_buffer); - - /* types */ - for (e = ste_ssid_head.tqh_first; e != NULL; e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - for (i = 0; i < max_ste_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_ste_types; - } - - if ((ptr - buf) != len) { - printf("ERROR: wrong lengths in %s.\n", __func__); - exit(EXIT_FAILURE); - } - (*len_ste) = len; - return buf; /* for now */ -} - -static ssize_t write_padded(int fd, const void *buf, size_t count) -{ - int rc; - static const char padding[7] = {0,0,0,0,0,0,0}; - unsigned int len = ROUND8(count) - count; - - rc = write(fd, buf, count); - if (rc == count && len > 0) { - write(fd, padding, len); - } - return rc; -} - -int write_binary(char *filename) -{ - struct acm_policy_buffer header; - unsigned char *ste_buffer = NULL, *chwall_buffer = - NULL, *policy_reference_buffer = NULL; - u_int32_t len; - int fd, ret = 0; - uint32_t major = 0, minor = 0; - - u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0; /* length of policy components */ - - if (policy_version_string) - sscanf(policy_version_string,"%d.%d", &major, &minor); - - /* open binary file */ - if ((fd = - open(filename, O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR)) <= 0) { - ret = -EIO; - goto out1; - } - policy_reference_buffer = write_policy_reference_binary(&len_pr); - ste_buffer = write_ste_binary(&len_ste); - chwall_buffer = write_chwall_binary(&len_chwall); - - /* determine primary component (default chwall) */ - header.policy_version = htonl(ACM_POLICY_VERSION); - header.magic = htonl(ACM_MAGIC); - header.xml_pol_version.major = htonl(major); - header.xml_pol_version.minor = htonl(minor); - - len = ROUND8(sizeof(struct acm_policy_buffer)); - if (have_chwall) - len += ROUND8(len_chwall); - if (have_ste) - len += ROUND8(len_ste); - len += ROUND8(len_pr); /* policy reference is mandatory */ - header.len = htonl(len); - - header.policy_reference_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer))); - - header.primary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr)); - if (primary == CHWALL) { - header.primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); - header.secondary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr) + - ROUND8(len_chwall)); - } else if (primary == STE) { - header.primary_policy_code = - htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - header.secondary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr) + - ROUND8(len_ste)); - } else { - /* null policy */ - header.primary_policy_code = htonl(ACM_NULL_POLICY); - header.secondary_buffer_offset = header.primary_buffer_offset; - } - - if (secondary == CHWALL) - header.secondary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); - else if (secondary == STE) - header.secondary_policy_code = - htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - else - header.secondary_policy_code = htonl(ACM_NULL_POLICY); - - if (write_padded(fd, (void *) &header, sizeof(struct acm_policy_buffer)) - != sizeof(struct acm_policy_buffer)) { - ret = -EIO; - goto out1; - } - - /* write label reference name */ - if (write_padded(fd, policy_reference_buffer, len_pr) != len_pr) { - ret = -EIO; - goto out1; - } - /* write primary policy component */ - if (primary == CHWALL) { - if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) { - ret = -EIO; - goto out1; - } - } else if (primary == STE) { - if (write_padded(fd, ste_buffer, len_ste) != len_ste) { - ret = -EIO; - goto out1; - } - } else; /* NULL POLICY has no policy data */ - - /* write secondary policy component */ - if (secondary == CHWALL) { - if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) { - ret = -EIO; - goto out1; - } - } else if (secondary == STE) { - if (write_padded(fd, ste_buffer, len_ste) != len_ste) { - ret = -EIO; - goto out1; - } - } else; /* NULL POLICY has no policy data */ - - out1: - /* cleanup */ - if (policy_reference_buffer) - free(policy_reference_buffer); - if (chwall_buffer) - free(chwall_buffer); - if (ste_buffer) - free(ste_buffer); - close(fd); - return ret; -} - -int is_valid(xmlDocPtr doc) -{ - int err = 0; - xmlSchemaPtr schema_ctxt = NULL; - xmlSchemaParserCtxtPtr schemaparser_ctxt = NULL; - xmlSchemaValidCtxtPtr schemavalid_ctxt = NULL; - - schemaparser_ctxt = xmlSchemaNewParserCtxt(schema_filename); - schema_ctxt = xmlSchemaParse(schemaparser_ctxt); - schemavalid_ctxt = xmlSchemaNewValidCtxt(schema_ctxt); - -#ifdef VALIDATE_SCHEMA - /* only tested to be available from libxml2-2.6.20 upwards */ - if ((err = xmlSchemaIsValid(schemavalid_ctxt)) != 1) { - printf("ERROR: Invalid schema file %s (err=%d)\n", - schema_filename, err); - err = -EIO; - goto out; - } else - printf("XML Schema %s valid.\n", schema_filename); -#endif - if ((err = xmlSchemaValidateDoc(schemavalid_ctxt, doc))) { - err = -EIO; - goto out; - } - out: - xmlSchemaFreeValidCtxt(schemavalid_ctxt); - xmlSchemaFreeParserCtxt(schemaparser_ctxt); - xmlSchemaFree(schema_ctxt); - return (err != 0) ? 0 : 1; -} - -int main(int argc, char **argv) -{ - xmlDocPtr policydoc = NULL; - - int err = EXIT_FAILURE; - - char *file_prefix; - int prefix_len; - - int opt_char; - char *policy_dir = POLICY_DIR; - - if (ACM_POLICY_VERSION != WRITTEN_AGAINST_ACM_POLICY_VERSION) { - printf - ("ERROR: This program was written against an older ACM version.\n"); - printf("ERROR: ACM_POLICY_VERSION=%d, WRITTEN AGAINST= %d.\n", - ACM_POLICY_VERSION, WRITTEN_AGAINST_ACM_POLICY_VERSION); - exit(EXIT_FAILURE); - } - - while ((opt_char = getopt(argc, argv, "d:")) != -1) { - switch (opt_char) { - case 'd': - policy_dir = malloc(strlen(optarg) + 2); /* null terminator and possibly "/" */ - if (!policy_dir) { - printf("ERROR allocating directory name memory.\n"); - exit(EXIT_FAILURE); - } - strcpy(policy_dir, optarg); - if (policy_dir[strlen(policy_dir) - 1] != '/') - strcat(policy_dir, "/"); - break; - - default: - usage(basename(argv[0])); - } - } - - if ((argc - optind) != 1) - usage(basename(argv[0])); - - printf("arg=%s\n", argv[optind]); - - prefix_len = - strlen(policy_dir) + strlen(argv[optind]) + - 1 /* null terminator */ ; - - file_prefix = malloc(prefix_len); - policy_filename = malloc(prefix_len + strlen(POLICY_EXTENSION)); - binary_filename = malloc(prefix_len + strlen(BINARY_EXTENSION)); - mapping_filename = malloc(prefix_len + strlen(MAPPING_EXTENSION)); - schema_filename = - malloc(strlen(policy_dir) + strlen(SCHEMA_FILENAME) + 1); - - if (!file_prefix || !policy_filename || - !binary_filename || !mapping_filename || !schema_filename) { - printf("ERROR allocating file name memory.\n"); - goto out2; - } - - /* create input/output filenames out of prefix */ - strcpy(file_prefix, policy_dir); - strcat(file_prefix, argv[optind]); - - strcpy(policy_filename, file_prefix); - strcpy(binary_filename, file_prefix); - strcpy(mapping_filename, file_prefix); - - strcat(policy_filename, POLICY_EXTENSION); - strcat(binary_filename, BINARY_EXTENSION); - strcat(mapping_filename, MAPPING_EXTENSION); - - strcpy(schema_filename, policy_dir); - strcat(schema_filename, SCHEMA_FILENAME); - - policydoc = xmlParseFile(policy_filename); - - if (policydoc == NULL) { - printf("Error: could not parse file %s.\n", argv[optind]); - goto out; - } - - printf("Validating policy file %s...\n", policy_filename); - - if (!is_valid(policydoc)) { - printf("ERROR: Failed schema-validation for file %s (err=%d)\n", - policy_filename, err); - goto out; - } - - /* create mappings */ - create_mappings(policydoc); - - /* write label mapping file */ - if (write_mapping(mapping_filename)) { - printf("ERROR: writing mapping file %s.\n", mapping_filename); - goto out; - } - - /* write binary file */ - if (write_binary(binary_filename)) { - printf("ERROR: writing binary file %s.\n", binary_filename); - goto out; - } - err = EXIT_SUCCESS; - /* write stats */ - if (have_chwall) { - printf("Max chwall labels: %u\n", max_chwall_labels); - printf("Max chwall-types: %u\n", max_chwall_types); - printf("Max chwall-ssids: %u\n", max_chwall_ssids); - } - - if (have_ste) { - printf("Max ste labels: %u\n", max_ste_labels); - printf("Max ste-types: %u\n", max_ste_types); - printf("Max ste-ssids: %u\n", max_ste_ssids); - } - /* cleanup */ - out: - xmlFreeDoc(policydoc); - out2: - xmlCleanupParser(); - return err; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/tools/security/secpol_xml2bin.h b/tools/security/secpol_xml2bin.h deleted file mode 100644 index 0afb85505c..0000000000 --- a/tools/security/secpol_xml2bin.h +++ /dev/null @@ -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 diff --git a/tools/xm-test/lib/XmTestLib/acm.py b/tools/xm-test/lib/XmTestLib/acm.py index 23564b5096..5e1c87627f 100644 --- a/tools/xm-test/lib/XmTestLib/acm.py +++ b/tools/xm-test/lib/XmTestLib/acm.py @@ -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): diff --git a/tools/xm-test/tests/security-acm/01_security-acm_basic.py b/tools/xm-test/tests/security-acm/01_security-acm_basic.py index 26666f1faa..7876c51d1b 100644 --- a/tools/xm-test/tests/security-acm/01_security-acm_basic.py +++ b/tools/xm-test/tests/security-acm/01_security-acm_basic.py @@ -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) diff --git a/tools/xm-test/tests/security-acm/acm_utils.py b/tools/xm-test/tests/security-acm/acm_utils.py index 29608a38a4..67857fb2d9 100644 --- a/tools/xm-test/tests/security-acm/acm_utils.py +++ b/tools/xm-test/tests/security-acm/acm_utils.py @@ -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) |