[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH][ACM][UPDATE] python tools and support for resource labeling



Same as previous patch, except that we no longer use xml marshaling.

Signed-off-by: Bryan D. Payne <bdpayne@xxxxxxxxxx>
Signed-off-by: Reiner Sailer <sailer@xxxxxxxxxx>



---
 docs/man/xm.pod.1                     |   93 +++++++++++++++++++--
 tools/python/xen/util/dictio.py       |   50 +++++++++++
 tools/python/xen/util/security.py     |   98 ++++++++++++++++++++++
 tools/python/xen/xend/server/blkif.py |   12 ++
 tools/python/xen/xm/addlabel.py       |  149 +++++++++++++++++++++++++++-------
 tools/python/xen/xm/create.py         |   59 ++++++++++++-
 tools/python/xen/xm/dry-run.py        |   95 +++++++++++++++++++++
 tools/python/xen/xm/getlabel.py       |  131 +++++++++++++++++++++++++++++
 tools/python/xen/xm/main.py           |   28 ++++++
 tools/python/xen/xm/resources.py      |   61 +++++++++++++
 tools/python/xen/xm/rmlabel.py        |  130 +++++++++++++++++++++++++++++
 11 files changed, 862 insertions(+), 44 deletions(-)

Index: xen-unstable.hg-shype/docs/man/xm.pod.1
===================================================================
--- xen-unstable.hg-shype.orig/docs/man/xm.pod.1
+++ xen-unstable.hg-shype/docs/man/xm.pod.1
@@ -875,14 +875,43 @@ defined in the I<policy>. Unless specifi
 the currently enforced access control policy. The default for I<type>
 is 'dom'. The labels are arranged in alphabetical order.
 
-=item B<addlabel> I<configfile> I<label> [I<policy>]
+=item B<addlabel> I<label> dom I<configfile> [I<policy>]
+
+=item B<addlabel> I<label> res I<resource> [I<policy>]
 
 Adds the security label with name I<label> to a domain
-I<configfile>. Unless specified, the default I<policy> is the
+I<configfile> (dom) or to the global resource label file for the
+given I<resource> (res). Unless specified, the default I<policy> is the
 currently enforced access control policy. This subcommand also
 verifies that the I<policy> definition supports the specified I<label>
 name.
 
+=item B<rmlabel> dom I<configfile>
+
+=item B<rmlabel> res I<resource>
+
+Works the same as the I<addlabel> command (above), except that this
+command will remove the label from the domain I<configfile> (dom) or
+the global resource label file (res).
+
+=item B<getlabel> dom I<configfile>
+
+=item B<getlabel> res I<resource>
+
+Shows the label for the given I<configfile> or I<resource>
+
+=item B<resources>
+
+Lists all resources in the global resource label file.  Each resource
+is listed with its associated label and policy name.
+
+=item B<dry-run> I<configfile>
+
+Determines if the specified I<configfile> describes a domain with a valid
+security configuration for type enforcement. The test shows the policy
+decision made for each resource label against the domain label as well as
+the overall decision.
+
 B<CONFIGURING SECURITY>
 
 =over 4
@@ -960,17 +989,18 @@ B<ATTACHING A SECURITY LABEL TO A DOMAIN
 
 =over 4
 
-This subcommand attaches a security label to a domain configuration
-file, here a HomeBanking label. The example policy ensures that this
-domain does not share information with other non-hombanking user
-domains (i.e., domains labeled as dom_Fun or dom_Boinc) and that it
-will not run simultaneously with domains labeled as dom_Fun.
+The I<addlabel> subcommand can attach a security label to a domain
+configuration file, here a HomeBanking label. The example policy
+ensures that this domain does not share information with other
+non-hombanking user domains (i.e., domains labeled as dom_Fun or
+dom_Boinc) and that it will not run simultaneously with domains
+labeled as dom_Fun.
 
 We assume that the specified myconfig.xm configuration file actually
 instantiates a domain that runs workloads related to home-banking,
 probably just a browser environment for online-banking.
 
-    xm addlabel myconfig.xm dom_HomeBanking
+    xm addlabel dom_HomeBanking dom myconfig.xm
 
 The very simple configuration file might now look as printed
 below. The I<addlabel> subcommand added the B<access_control> entry at
@@ -997,6 +1027,38 @@ permitted".
 
 =back
 
+B<ATTACHING A SECURITY LABEL TO A RESOURCE>
+
+=over 4
+
+The I<addlabel> subcommand can also be used to attach a security
+label to a resource. Following the home banking example from above,
+we can label a disk resource (e.g., a physical partition or a file)
+to make it accessible to the home banking domain. The example policy
+provides a resource label, res_LogicalDiskPartition1(hda1), that is
+compatible with the HomeBanking domain label.
+
+    xm addlabel "res_LogicalDiskPartition1(hda1)" res phy:hda6
+
+After labeling this disk resource, it can be attached to the domain
+by adding a line to the domain configuration file. The line below
+attaches this disk to the domain at boot time.
+
+    disk = [ 'phy:hda6,sda2,w' ]
+
+Alternatively, the resource can be attached after booting the domain
+by using the I<block-attach> subcommand.
+
+    xm block-attach homebanking phy:hda6 sda2 w
+
+Note that labeled resources cannot be used when security is turned
+off.  Any attempt to use labeled resources with security turned off
+will result in a failure with a corresponding error message.  The
+solution is to enable security or, if security is no longer desired,
+to remove the resource label using the I<rmlabel> subcommand.
+
+=back
+
 B<STARTING AND LISTING LABELED DOMAINS>
 
 =over 4
@@ -1011,6 +1073,21 @@ B<STARTING AND LISTING LABELED DOMAINS>
 
 =back
 
+B<LISTING LABELED RESOURCES>
+
+=over 4
+
+    xm resources
+
+      phy:hda6
+          policy: example.chwall_ste.client_v1
+          label:  res_LogicalDiskPartition1(hda1)
+      file:/xen/disk_image/disk.img
+          policy: example.chwall_ste.client_v1
+          label:  res_LogicalDiskPartition2(hda2)
+
+=back
+
 B<POLICY REPRESENTATIONS>
 
 =over 4
Index: xen-unstable.hg-shype/tools/python/xen/util/dictio.py
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/python/xen/util/dictio.py
@@ -0,0 +1,50 @@
+#===========================================================================
+# 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: Bryan D. Payne <bdpayne@xxxxxxxxxx>
+#============================================================================
+
+
+def dict_read(dictname, filename):
+    """Loads <filename> and returns the dictionary named <dictname> from
+       the file.
+    """
+    dict = {}
+
+    # read in the config file
+    globs = {}
+    locs = {}
+    execfile(filename, globs, locs)
+
+    for (k, v) in locs.items():
+        if k == dictname:
+            dict = v
+            break
+
+    return dict
+
+def dict_write(dict, dictname, filename):
+    """Writes <dict> to <filename> using the name <dictname>.  If the file
+       contains any other data, it will be overwritten.
+    """
+    prefix = dictname + " = {\n"
+    suffix = "}\n"
+    fd = open(filename, "wb")
+    fd.write(prefix)
+    for key in dict:
+        line = "    '" + str(key) + "': " + str(dict[key]) + ",\n"
+        fd.write(line)
+    fd.write(suffix)
+    fd.close()
Index: xen-unstable.hg-shype/tools/python/xen/util/security.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/util/security.py
+++ xen-unstable.hg-shype/tools/python/xen/util/security.py
@@ -14,6 +14,7 @@
 #============================================================================
 # Copyright (C) 2006 International Business Machines Corp.
 # Author: Reiner Sailer
+# Author: Bryan D. Payne <bdpayne@xxxxxxxxxx>
 #============================================================================
 
 import commands
@@ -23,9 +24,12 @@ import traceback
 import shutil
 from xen.lowlevel import acm
 from xen.xend import sxp
+from xen.xend.XendLogging import log
+from xen.util import dictio
 
 #global directories and tools for security management
 policy_dir_prefix = "/etc/xen/acm-security/policies"
+res_label_filename = policy_dir_prefix + "/resource_labels"
 boot_filename = "/boot/grub/menu.lst"
 xensec_xml2bin = "/usr/sbin/xensec_xml2bin"
 xensec_tool = "/usr/sbin/xensec_tool"
@@ -530,3 +534,97 @@ def list_labels(policy_name, condition):
             if label not in labels:
                 labels.append(label)
     return labels
+
+
+def get_res_label(resource):
+    """Returns resource label information (label, policy) if it exists.
+       Otherwise returns null label and policy.
+    """
+    def default_res_label():
+        ssidref = NULL_SSIDREF
+        if on():
+            label = ssidref2label(ssidref)
+        else:
+            label = None
+        return (label, 'NULL')
+
+    (label, policy) = default_res_label()
+
+    # load the resource label file
+    res_label_cache = {}
+    try:
+        res_label_cache = dictio.dict_read("resources", res_label_filename)
+    except:
+        log.info("Resource label file not found.")
+        return default_res_label()
+
+    # find the resource information
+    if res_label_cache.has_key(resource):
+        (policy, label) = res_label_cache[resource]
+
+    return (label, policy)
+
+
+def get_res_security_details(resource):
+    """Returns the (label, ssidref, policy) associated with a given
+       resource from the global resource label file.
+    """
+    def default_security_details():
+        ssidref = NULL_SSIDREF
+        if on():
+            label = ssidref2label(ssidref)
+        else:
+            label = None
+        policy = active_policy
+        return (label, ssidref, policy)
+
+    (label, ssidref, policy) = default_security_details()
+
+    # find the entry associated with this resource
+    (label, policy) = get_res_label(resource)
+    if policy == 'NULL':
+        log.info("Resource label for "+resource+" not in file, using DEFAULT.")
+        return default_security_details()
+
+    # is this resource label for the running policy?
+    if policy == active_policy:
+        ssidref = label2ssidref(label, policy, 'res')
+    else:
+        log.info("Resource label not for active policy, using DEFAULT.")
+        return default_security_details()
+
+    return (label, ssidref, policy)
+
+
+def res_security_check(resource, domain_label):
+    """Checks if the given resource can be used by the given domain
+       label.  Returns 1 if the resource can be used, otherwise 0.
+    """
+    rtnval = 1
+
+    # if security is on, ask the hypervisor for a decision
+    if on():
+        (label, ssidref, policy) = get_res_security_details(resource)
+        domac = ['access_control']
+        domac.append(['policy', active_policy])
+        domac.append(['label', domain_label])
+        domac.append(['type', 'dom'])
+        decision = get_decision(domac, ['ssidref', str(ssidref)])
+
+        # provide descriptive error messages
+        if decision == 'DENIED':
+            if label == ssidref2label(NULL_SSIDREF):
+                raise ACMError("Resource '"+resource+"' is not labeled")
+                rtnval = 0
+            else:
+                raise ACMError("Permission denied for resource '"+resource+"' 
because label '"+label+"' is not allowed")
+                rtnval = 0
+
+    # security is off, make sure resource isn't labeled
+    else:
+        (label, policy) = get_res_label(resource)
+        if policy != 'NULL':
+            raise ACMError("Security is off, but '"+resource+"' is labeled")
+            rtnval = 0
+
+    return rtnval
Index: xen-unstable.hg-shype/tools/python/xen/xend/server/blkif.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xend/server/blkif.py
+++ xen-unstable.hg-shype/tools/python/xen/xend/server/blkif.py
@@ -21,6 +21,7 @@ import re
 import string
 
 from xen.util import blkif
+from xen.util import security
 from xen.xend import sxp
 from xen.xend.XendError import VmError
 
@@ -40,15 +41,22 @@ class BlkifController(DevController):
 
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
+        uname = sxp.child_value(config, 'uname')
 
         dev = sxp.child_value(config, 'dev')
 
-        (typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1)
+        (typ, params) = string.split(uname, ':', 1)
         back = { 'dev'    : dev,
                  'type'   : typ,
                  'params' : params,
                  'mode'   : sxp.child_value(config, 'mode', 'r')
-                 }
+               }
+
+        if security.on():
+            (label, ssidref, policy) = security.get_res_security_details(uname)
+            back.update({'acm_label'  : label,
+                         'acm_ssidref': str(ssidref),
+                         'acm_policy' : policy})
 
         if 'ioemu:' in dev:
             (dummy, dev1) = string.split(dev, ':', 1)
Index: xen-unstable.hg-shype/tools/python/xen/xm/addlabel.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xm/addlabel.py
+++ xen-unstable.hg-shype/tools/python/xen/xm/addlabel.py
@@ -14,61 +14,150 @@
 #============================================================================
 # Copyright (C) 2006 International Business Machines Corp.
 # Author: Reiner Sailer <sailer@xxxxxxxxxx>
+# Author: Bryan D. Payne <bdpayne@xxxxxxxxxx>
 #============================================================================
 
-"""Labeling a domain configuration file.
+"""Labeling a domain configuration file or a resoruce.
 """
 import sys, os
+import string
 import traceback
-
-
-from xen.util.security import ACMError, err, active_policy, label2ssidref, on, 
access_control_re
-
+from xen.util import dictio
+from xen.util import security
 
 def usage():
-    print "\nUsage: xm addlabel <configfile> <label> [<policy>]\n"
-    print "  This program adds an acm_label entry into the 'configfile'."
-    print "  It derives the policy from the running hypervisor if it"
-    print "  is not given (optional parameter). If the configfile is"
-    print "  already labeled, then addlabel fails.\n"
-    err("Usage")
-
+    print "\nUsage: xm addlabel <label> dom <configfile> [<policy>]"
+    print "       xm addlabel <label> res <resource> [<policy>]\n"
+    print "  This program adds an acm_label entry into the 'configfile'"
+    print "  for a domain or to the global resource label file for a"
+    print "  resource. It derives the policy from the running hypervisor"
+    print "  if it is not given (optional parameter). If a label already"
+    print "  exists for the given domain or resource, then addlabel fails.\n"
+    security.err("Usage")
+
+def validate_config_file(configfile):
+    """Performs a simple sanity check on the configuration file passed on
+       the command line.  We basically just want to make sure that it's
+       not a domain image file so we check for a few configuration values
+       and then we are satisfied.  Returned 1 on success, otherwise 0.
+    """
+    # read in the config file
+    globs = {}
+    locs = {}
+    try:
+        execfile(configfile, globs, locs)
+    except:
+        print "Invalid configuration file."
+        return 0
 
-def main(argv):
+    # sanity check on the data from the file
+    count = 0
+    required = ['kernel', 'memory', 'name']
+    for (k, v) in locs.items():
+        if k in required:
+            count += 1
+    if count != 3:
+        print "Invalid configuration file."
+        return 0
+    else:
+        return 1
+
+
+def add_resource_label(label, resource, policyref):
+    """Adds a resource label to the global resource label file.
+    """
     try:
-        policyref = None
-        if len(argv) not in [3,4]:
-            usage()
-        configfile = argv[1]
-        label = argv[2]
+        # sanity check: make sure this label can be instantiated later on
+        ssidref = security.label2ssidref(label, policyref, 'res')
 
-        if len(argv) == 4:
-            policyref = argv[3]
-        elif on():
-            policyref = active_policy
-        else:
-            err("No active policy. Policy must be specified in command line.")
+        # sanity check on resource name
+        (type, file) = resource.split(":")
+        if type == "phy":
+            file = "/dev/" + file
+        if not os.path.exists(file):
+            print "Invalid resource '"+resource+"'"
+            return
+
+        # see if this resource is already in the file
+        access_control = {}
+        file = security.res_label_filename
+        try:
+            access_control = dictio.dict_read("resources", file)
+        except:
+            print "Resource file not found, creating new file at:"
+            print "%s" % (file)
+
+        if access_control.has_key(resource):
+            security.err("This resource is already labeled.")
+
+        # write the data to file
+        new_entry = { resource : tuple([policyref, label]) }
+        access_control.update(new_entry)
+        dictio.dict_write(access_control, "resources", file)
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
 
-        #sanity checks: make sure this label can be instantiated later on
-        ssidref = label2ssidref(label, policyref, 'dom')
+def add_domain_label(label, configfile, policyref):
+    try:
+        # sanity checks: make sure this label can be instantiated later on
+        ssidref = security.label2ssidref(label, policyref, 'dom')
 
         new_label = "access_control = ['policy=%s,label=%s']\n" % (policyref, 
label)
         if not os.path.isfile(configfile):
-            err("Configuration file \'" + configfile + "\' not found.")
+            security.err("Configuration file \'" + configfile + "\' not 
found.")
         config_fd = open(configfile, "ra+")
         for line in config_fd:
-            if not access_control_re.match(line):
+            if not security.access_control_re.match(line):
                 continue
             config_fd.close()
-            err("Config file \'" + configfile + "\' is already labeled.")
+            security.err("Config file \'" + configfile + "\' is already 
labeled.")
         config_fd.write(new_label)
         config_fd.close()
 
-    except ACMError:
+    except security.ACMError:
         pass
     except:
         traceback.print_exc(limit=1)
 
+def main (argv):
+    try:
+        policyref = None
+        if len(argv) not in [4,5]:
+            usage()
+        label = argv[1]
+
+        if len(argv) == 5:
+            policyref = argv[4]
+        elif security.on():
+            policyref = security.active_policy
+        else:
+            security.err("No active policy. Policy must be specified in 
command line.")
+
+        if argv[2].lower() == "dom":
+            configfile = argv[3]
+            if configfile[0] != '/':
+                for prefix in [".", "/etc/xen"]:
+                    configfile = prefix + "/" + configfile
+                    if os.path.isfile(configfile):
+                        fd = open(configfile, "rb")
+                        break
+            if not validate_config_file(configfile):
+                usage()
+            else:
+                add_domain_label(label, configfile, policyref)
+        elif argv[2].lower() == "res":
+            resource = argv[3]
+            add_resource_label(label, resource, policyref)
+        else:
+            usage()
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
 
 if __name__ == '__main__':
     main(sys.argv)
Index: xen-unstable.hg-shype/tools/python/xen/xm/create.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xm/create.py
+++ xen-unstable.hg-shype/tools/python/xen/xm/create.py
@@ -988,6 +988,56 @@ def parseCommandLine(argv):
     return (gopts, config)
 
 
+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():
+        domain_label = security.ssidref2label(security.NULL_SSIDREF)
+        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)
+            (res_label, res_policy) = security.get_res_label(resource)
+            print "   --> res:"+res_label+" ("+res_policy+")"
+            print "   --> dom:"+domain_label+" ("+domain_policy+")"
+            answer = 0
+
+    return answer
+
+
 def main(argv):
     try:
         (opts, config) = parseCommandLine(argv)
@@ -1000,9 +1050,12 @@ def main(argv):
     if opts.vals.dryrun:
         PrettyPrint.prettyprint(config)
     else:
-        dom = make_domain(opts, config)
-        if opts.vals.console_autoconnect:
-            console.execConsole(dom)
+        if not config_security_check(config, verbose=0):
+            err("Resource access violation")
+        else:
+            dom = make_domain(opts, config)
+            if opts.vals.console_autoconnect:
+                console.execConsole(dom)
         
 if __name__ == '__main__':
     main(sys.argv)
Index: xen-unstable.hg-shype/tools/python/xen/xm/dry-run.py
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/python/xen/xm/dry-run.py
@@ -0,0 +1,95 @@
+#============================================================================
+# 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: Bryan D. Payne <bdpayne@xxxxxxxxxx>
+#============================================================================
+
+"""Tests the security settings for a domain and its resources.
+"""
+from xen.util import security
+from xen.xm import create
+from xen.xend import sxp
+
+def usage():
+    print "\nUsage: xm dry-run <configfile>\n"
+    print "This program checks each resource listed in the configfile"
+    print "to see if the domain created by the configfile can access"
+    print "the resources.  The status of each resource is listed"
+    print "individually along with the final security decision.\n"
+
+
+def check_domain_label(config):
+    """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
+    secon = 0
+    default_label = security.ssidref2label(security.NULL_SSIDREF)
+    if security.on():
+        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
+    print "Checking domain:"
+    if (not secon) and (not dom_label):
+        print "   %s: PERMITTED" % (dom_name)
+        answer = 1
+    elif (secon) and (dom_label) and (dom_label != default_label):
+        print "   %s: PERMITTED" % (dom_name)
+        answer = 1
+    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 main (argv):
+    if len(argv) != 2:
+        usage()
+        return
+
+    try:
+        passed = 0
+        (opts, config) = create.parseCommandLine(argv)
+        if check_domain_label(config):
+            if create.config_security_check(config, verbose=1):
+                passed = 1
+        else:
+            print "Checking resources: (skipped)"
+
+        if passed:
+            print "Dry Run: PASSED"
+        else:
+            print "Dry Run: FAILED"
+    except security.ACMError:
+        pass
+
+
+if __name__ == '__main__':
+    main(sys.argv)
Index: xen-unstable.hg-shype/tools/python/xen/xm/getlabel.py
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/python/xen/xm/getlabel.py
@@ -0,0 +1,131 @@
+#============================================================================
+# 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: Bryan D. Payne <bdpayne@xxxxxxxxxx>
+#============================================================================
+
+"""Show the label for a domain or resoruce.
+"""
+import sys, os, re
+import string
+import traceback
+from xen.util import dictio
+from xen.util import security
+
+def usage():
+    print "\nUsage: xm getlabel dom <configfile>"
+    print "       xm getlabel res <resource>\n"
+    print "  This program shows the label for a domain or resource.\n"
+
+
+def get_resource_label(resource):
+    """Gets the resource label
+    """
+    # read in the resource file
+    file = security.res_label_filename
+    try:
+        access_control = dictio.dict_read("resources", file)
+    except:
+        print "Resource label file not found"
+        return
+
+    try:
+        # get the entry and print label
+        if access_control.has_key(resource):
+            policy = access_control[resource][0]
+            label = access_control[resource][1]
+            print "policy="+policy+",label="+label
+        else:
+            print "Resource not labeled"
+            return
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
+
+
+def get_domain_label(configfile):
+    try:
+        # open the domain config file
+        fd = None
+        file = None
+        if configfile[0] == '/':
+            fd = open(configfile, "rb")
+        else:
+            for prefix in [".", "/etc/xen"]:
+                file = prefix + "/" + configfile
+                if os.path.isfile(file):
+                    fd = open(file, "rb")
+                    break
+        if not fd:
+            print "Configuration file '"+configfile+"' not found."
+            return
+
+        # read in the domain config file, finding the label line
+        ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE)
+        ac_exit_re = re.compile(".*'\].*")
+        acline = ""
+        record = 0
+        for line in fd.readlines():
+            if ac_entry_re.match(line):
+                record = 1
+            if record:
+                acline = acline + line
+            if record and ac_exit_re.match(line):
+                record = 0
+        fd.close()
+
+        # send error message if we didn't find anything
+        if acline == "":
+            print "Label does not exist in domain configuration file."
+            return
+
+        # print out the label
+        (title, data) = acline.split("=", 1)
+        data = data.strip()
+        data = data.lstrip("[\'")
+        data = data.rstrip("\']")
+        print data
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
+
+
+def main (argv):
+    try:
+        if len(argv) != 3:
+            usage()
+            return
+
+        if argv[1].lower() == "dom":
+            configfile = argv[2]
+            get_domain_label(configfile)
+        elif argv[1].lower() == "res":
+            resource = argv[2]
+            get_resource_label(resource)
+        else:
+            usage()
+
+    except security.ACMError:
+        traceback.print_exc(limit=1)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
+
+
Index: xen-unstable.hg-shype/tools/python/xen/xm/main.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xm/main.py
+++ xen-unstable.hg-shype/tools/python/xen/xm/main.py
@@ -30,6 +30,7 @@ import socket
 import warnings
 warnings.filterwarnings('ignore', category=FutureWarning)
 import xmlrpclib
+import traceback
 
 import xen.xend.XendProtocol
 
@@ -119,7 +120,11 @@ vnet_list_help = "vnet-list [-l|--long] 
 vnet_create_help = "vnet-create <config>             create a vnet from a 
config file"
 vnet_delete_help = "vnet-delete <vnetid>             delete a vnet"
 vtpm_list_help = "vtpm-list <DomId> [--long]       list virtual TPM devices"
-addlabel_help =  "addlabel <ConfigFile> <label>    Add security label to 
ConfigFile"
+addlabel_help =  "addlabel <label> dom <configfile> Add security label to 
domain\n            <label> res <resource>   or resource"
+rmlabel_help =  "rmlabel dom <configfile>         Remove security label from 
domain\n           res <resource>           or resource"
+getlabel_help =  "getlabel dom <configfile>        Show security label for 
domain\n            res <resource>          or resource"
+dry_run_help =  "dry-run <configfile>             Tests if domain can access 
its resources"
+resources_help =  "resources                        Show info for each labeled 
resource"
 cfgbootpolicy_help = "cfgbootpolicy <policy>           Add policy to boot 
configuration "
 dumppolicy_help = "dumppolicy                       Print hypervisor ACM state 
information"
 loadpolicy_help = "loadpolicy <policy>              Load binary policy into 
hypervisor"
@@ -203,6 +208,10 @@ vnet_commands = [
 acm_commands = [
     "labels",
     "addlabel",
+    "rmlabel",
+    "getlabel",
+    "dry-run",
+    "resources",
     "makepolicy",
     "loadpolicy",
     "cfgbootpolicy",
@@ -999,6 +1008,19 @@ def xm_block_attach(args):
     if len(args) == 5:
         vbd.append(['backend', args[4]])
 
+    # verify that policy permits attaching this resource
+    try:
+        dominfo = server.xend.domain(dom)
+        domid = sxp.child_value(dominfo, 'domid')
+        (tmp1, label, tmp2, tmp3) = security.get_ssid(domid)
+        security.res_security_check(args[1], label)
+    except security.ACMError, e:
+        print e.value
+        sys.exit(1)
+    except:
+        traceback.print_exc(limit=1)
+        sys.exit(1)
+
     server.xend.domain.device_create(dom, vbd)
 
 
@@ -1131,6 +1153,10 @@ subcommands = [
     'shutdown',
     'labels',
     'addlabel',
+    'rmlabel',
+    'getlabel',
+    'dry-run',
+    'resources',
     'cfgbootpolicy',
     'makepolicy',
     'loadpolicy',
Index: xen-unstable.hg-shype/tools/python/xen/xm/resources.py
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/python/xen/xm/resources.py
@@ -0,0 +1,61 @@
+#============================================================================
+# 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: Bryan D. Payne <bdpayne@xxxxxxxxxx>
+#============================================================================
+
+"""List the resource label information from the global resource label file
+"""
+import sys, os
+import string
+import traceback
+from xen.util import dictio
+from xen.util import security
+
+def usage():
+    print "\nUsage: xm resource\n"
+    print "  This program lists information for each resource in the"
+    print "  global resource label file\n"
+
+
+def print_resource_data(access_control):
+    """Prints out a resource dictionary to stdout
+    """
+    for resource in access_control:
+        (policy, label) = access_control[resource]
+        print resource
+        print "    policy: "+policy
+        print "    label:  "+label
+
+
+def main (argv):
+    try:
+        file = security.res_label_filename
+        access_control = dictio.dict_read("resources", file)
+    except:
+        security.err("Resource file not found.")
+
+    try:
+        print_resource_data(access_control)
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
+
+
Index: xen-unstable.hg-shype/tools/python/xen/xm/rmlabel.py
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/python/xen/xm/rmlabel.py
@@ -0,0 +1,130 @@
+#============================================================================
+# 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: Bryan D. Payne <bdpayne@xxxxxxxxxx>
+#============================================================================
+
+"""Remove a label from a domain configuration file or a resoruce.
+"""
+import sys, os, re
+import string
+import traceback
+from xen.util import dictio
+from xen.util import security
+
+def usage():
+    print "\nUsage: xm rmlabel dom <configfile>"
+    print "       xm rmlabel res <resource>\n"
+    print "  This program removes an acm_label entry from the 'configfile'"
+    print "  for a domain or from the global resource label file for a"
+    print "  resource. If the label does not exist for the given domain or"
+    print "  resource, then rmlabel fails.\n"
+
+
+def rm_resource_label(resource):
+    """Removes a resource label from the global resource label file.
+    """
+    # read in the resource file
+    file = security.res_label_filename
+    try:
+        access_control = dictio.dict_read("resources", file)
+    except:
+        security.err("Resource file not found, cannot remove label!")
+
+    try:
+        # remove the entry and update file
+        if access_control.has_key(resource):
+            del access_control[resource]
+            dictio.dict_write(access_control, "resources", file)
+        else:
+            security.err("Label does not exist in resource label file.")
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
+
+
+def rm_domain_label(configfile):
+    try:
+        # open the domain config file
+        fd = None
+        file = None
+        if configfile[0] == '/':
+            fd = open(configfile, "rb")
+        else:
+            for prefix in [".", "/etc/xen"]:
+                file = prefix + "/" + configfile
+                if os.path.isfile(file):
+                    fd = open(file, "rb")
+                    break
+        if not fd:
+            security.err("Configuration file '"+configfile+"' not found.")
+
+        # read in the domain config file, removing label
+        ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE)
+        ac_exit_re = re.compile(".*'\].*")
+        file_contents = ""
+        comment = 0
+        removed = 0
+        for line in fd.readlines():
+            if ac_entry_re.match(line):
+                comment = 1
+            if comment:
+                removed = 1
+                line = "#"+line
+            if comment and ac_exit_re.match(line):
+                comment = 0
+            file_contents = file_contents + line
+        fd.close()
+
+        # send error message if we didn't find anything to remove
+        if not removed:
+            security.err("Label does not exist in domain configuration file.")
+
+        # write the data back out to the file
+        fd = open(file, "wb")
+        fd.writelines(file_contents)
+        fd.close()
+
+    except security.ACMError:
+        pass
+    except:
+        traceback.print_exc(limit=1)
+
+
+def main (argv):
+    try:
+        if len(argv) != 3:
+            usage()
+            return
+
+        if argv[1].lower() == "dom":
+            configfile = argv[2]
+            rm_domain_label(configfile)
+        elif argv[1].lower() == "res":
+            resource = argv[2]
+            rm_resource_label(resource)
+        else:
+            usage()
+
+    except security.ACMError:
+        traceback.print_exc(limit=1)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
+
+
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.