ia64/xen-unstable

diff tools/python/xen/util/security.py @ 10720:8922c1fbe684

[XM][ACM] Add xm subcommands to work with security resource labels.

This patch adds new xm subcommands to support working with resource
labels. The new subcommands are 'xm resources', 'xm rmlabel', 'xm
getlabel' and 'xm dry-run'. In addition, the 'xm addlabel' subcommand
now uses an updated syntax to support labeling both domains and
resources. See the xm man page for details on each subcommand.

Beyond the new subcommands, this patch allows users to immediately see
when security checks will fail by pushing some basic security checking
into the beginning of 'xm create' and 'xm block-attach'. ACM security
attributes for block devices are added to XenStore in order to support
the final security enforcement, which will be performed in the kernel
and included in a separate patch.

Signed-off-by: Bryan D. Payne <bdpayne@us.ibm.com>
Signed-off-by: Reiner Sailer <sailer@us.ibm.com>
author kfraser@localhost.localdomain
date Mon Jul 10 17:18:07 2006 +0100 (2006-07-10)
parents 0de8a4a023d0
children 58144f4b102c
line diff
     1.1 --- a/tools/python/xen/util/security.py	Mon Jul 10 17:05:44 2006 +0100
     1.2 +++ b/tools/python/xen/util/security.py	Mon Jul 10 17:18:07 2006 +0100
     1.3 @@ -14,6 +14,7 @@
     1.4  #============================================================================
     1.5  # Copyright (C) 2006 International Business Machines Corp.
     1.6  # Author: Reiner Sailer
     1.7 +# Author: Bryan D. Payne <bdpayne@us.ibm.com>
     1.8  #============================================================================
     1.9  
    1.10  import commands
    1.11 @@ -23,9 +24,12 @@ import traceback
    1.12  import shutil
    1.13  from xen.lowlevel import acm
    1.14  from xen.xend import sxp
    1.15 +from xen.xend.XendLogging import log
    1.16 +from xen.util import dictio
    1.17  
    1.18  #global directories and tools for security management
    1.19  policy_dir_prefix = "/etc/xen/acm-security/policies"
    1.20 +res_label_filename = policy_dir_prefix + "/resource_labels"
    1.21  boot_filename = "/boot/grub/menu.lst"
    1.22  xensec_xml2bin = "/usr/sbin/xensec_xml2bin"
    1.23  xensec_tool = "/usr/sbin/xensec_tool"
    1.24 @@ -530,3 +534,97 @@ def list_labels(policy_name, condition):
    1.25              if label not in labels:
    1.26                  labels.append(label)
    1.27      return labels
    1.28 +
    1.29 +
    1.30 +def get_res_label(resource):
    1.31 +    """Returns resource label information (label, policy) if it exists.
    1.32 +       Otherwise returns null label and policy.
    1.33 +    """
    1.34 +    def default_res_label():
    1.35 +        ssidref = NULL_SSIDREF
    1.36 +        if on():
    1.37 +            label = ssidref2label(ssidref)
    1.38 +        else:
    1.39 +            label = None
    1.40 +        return (label, 'NULL')
    1.41 +
    1.42 +    (label, policy) = default_res_label()
    1.43 +
    1.44 +    # load the resource label file
    1.45 +    res_label_cache = {}
    1.46 +    try:
    1.47 +        res_label_cache = dictio.dict_read("resources", res_label_filename)
    1.48 +    except:
    1.49 +        log.info("Resource label file not found.")
    1.50 +        return default_res_label()
    1.51 +
    1.52 +    # find the resource information
    1.53 +    if res_label_cache.has_key(resource):
    1.54 +        (policy, label) = res_label_cache[resource]
    1.55 +
    1.56 +    return (label, policy)
    1.57 +
    1.58 +
    1.59 +def get_res_security_details(resource):
    1.60 +    """Returns the (label, ssidref, policy) associated with a given
    1.61 +       resource from the global resource label file.
    1.62 +    """
    1.63 +    def default_security_details():
    1.64 +        ssidref = NULL_SSIDREF
    1.65 +        if on():
    1.66 +            label = ssidref2label(ssidref)
    1.67 +        else:
    1.68 +            label = None
    1.69 +        policy = active_policy
    1.70 +        return (label, ssidref, policy)
    1.71 +
    1.72 +    (label, ssidref, policy) = default_security_details()
    1.73 +
    1.74 +    # find the entry associated with this resource
    1.75 +    (label, policy) = get_res_label(resource)
    1.76 +    if policy == 'NULL':
    1.77 +        log.info("Resource label for "+resource+" not in file, using DEFAULT.")
    1.78 +        return default_security_details()
    1.79 +
    1.80 +    # is this resource label for the running policy?
    1.81 +    if policy == active_policy:
    1.82 +        ssidref = label2ssidref(label, policy, 'res')
    1.83 +    else:
    1.84 +        log.info("Resource label not for active policy, using DEFAULT.")
    1.85 +        return default_security_details()
    1.86 +
    1.87 +    return (label, ssidref, policy)
    1.88 +
    1.89 +
    1.90 +def res_security_check(resource, domain_label):
    1.91 +    """Checks if the given resource can be used by the given domain
    1.92 +       label.  Returns 1 if the resource can be used, otherwise 0.
    1.93 +    """
    1.94 +    rtnval = 1
    1.95 +
    1.96 +    # if security is on, ask the hypervisor for a decision
    1.97 +    if on():
    1.98 +        (label, ssidref, policy) = get_res_security_details(resource)
    1.99 +        domac = ['access_control']
   1.100 +        domac.append(['policy', active_policy])
   1.101 +        domac.append(['label', domain_label])
   1.102 +        domac.append(['type', 'dom'])
   1.103 +        decision = get_decision(domac, ['ssidref', str(ssidref)])
   1.104 +
   1.105 +        # provide descriptive error messages
   1.106 +        if decision == 'DENIED':
   1.107 +            if label == ssidref2label(NULL_SSIDREF):
   1.108 +                raise ACMError("Resource '"+resource+"' is not labeled")
   1.109 +                rtnval = 0
   1.110 +            else:
   1.111 +                raise ACMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed")
   1.112 +                rtnval = 0
   1.113 +
   1.114 +    # security is off, make sure resource isn't labeled
   1.115 +    else:
   1.116 +        (label, policy) = get_res_label(resource)
   1.117 +        if policy != 'NULL':
   1.118 +            raise ACMError("Security is off, but '"+resource+"' is labeled")
   1.119 +            rtnval = 0
   1.120 +
   1.121 +    return rtnval