components/openstack/glance/patches/07-CVE-2014-9493.patch
changeset 3998 5bd484384122
parent 3997 0ca3f3d6c919
child 4002 95b8f35fcdd5
equal deleted inserted replaced
3997:0ca3f3d6c919 3998:5bd484384122
     1 This patch fixes bug 1400966 for Havana.
       
     2 https://bugs.launchpad.net/glance/+bug/1400966
       
     3 
       
     4 commit 8bdb7ed9f5beaf816e7abba726904646bf3680dd
       
     5 Author: Zhi Yan Liu <[email protected]>
       
     6 Date:   Mon Dec 15 12:29:55 2014 +0800
       
     7 
       
     8     To prevent client use v2 patch api to handle file and swift location
       
     9 
       
    10     The change will be used to restrict client to download and delete any
       
    11     file in glance-api server. The same resone and logic as what we did in
       
    12     v1:
       
    13     https://github.com/openstack/glance/blob/master/glance/api/v1/images.py#L429
       
    14 
       
    15     Closes-Bug: bug/1400966
       
    16     DocImpact
       
    17 
       
    18     Conflicts:
       
    19         glance/api/v1/images.py
       
    20         glance/common/store_utils.py
       
    21         glance/location.py
       
    22         glance/tests/functional/v1/test_copy_to_file.py
       
    23         glance/tests/functional/v2/test_images.py
       
    24         glance/tests/unit/test_store_image.py
       
    25         glance/tests/unit/test_store_location.py
       
    26         glance/tests/unit/utils.py
       
    27         glance/tests/unit/v1/test_api.py
       
    28 
       
    29     (cherry picked from commit 4afdb017aa1ccef01482f117cb8d0736a6da38ed)
       
    30     Signed-off-by: Zhi Yan Liu <[email protected]>
       
    31     Change-Id: I72dbead3cb2dcb87f52658ddb880e26880cc229b 
       
    32 
       
    33 --- glance-2013.2.3/glance/api/v1/images.py.orig	2014-12-23 08:16:59.633230138 -0800
       
    34 +++ glance-2013.2.3/glance/api/v1/images.py	2014-12-23 08:19:15.059375018 -0800
       
    35 @@ -50,7 +50,8 @@ import glance.registry.client.v1.api as
       
    36  from glance.store import (get_from_backend,
       
    37                            get_size_from_backend,
       
    38                            get_store_from_location,
       
    39 -                          get_store_from_scheme)
       
    40 +                          get_store_from_scheme,
       
    41 +                          validate_external_location)
       
    42  
       
    43  LOG = logging.getLogger(__name__)
       
    44  SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS
       
    45 @@ -375,20 +376,19 @@ class Controller(controller.BaseControll
       
    46      @staticmethod
       
    47      def _validate_source(source, req):
       
    48          """
       
    49 -        External sources (as specified via the location or copy-from headers)
       
    50 -        are supported only over non-local store types, i.e. S3, Swift, HTTP.
       
    51 -        Note the absence of file:// for security reasons, see LP bug #942118.
       
    52 -        If the above constraint is violated, we reject with 400 "Bad Request".
       
    53 +        To validate if external sources (as specified via the location
       
    54 +        or copy-from headers) are supported. Otherwise we reject
       
    55 +        with 400 "Bad Request".
       
    56          """
       
    57          if source:
       
    58 -            for scheme in ['s3', 'swift', 'http', 'rbd', 'sheepdog', 'cinder']:
       
    59 -                if source.lower().startswith(scheme):
       
    60 -                    return source
       
    61 -            msg = _("External sourcing not supported for store %s") % source
       
    62 -            LOG.debug(msg)
       
    63 -            raise HTTPBadRequest(explanation=msg,
       
    64 -                                 request=req,
       
    65 -                                 content_type="text/plain")
       
    66 +            if validate_external_location(source):
       
    67 +                return source
       
    68 +            else:
       
    69 +                msg = _("External source are not supported: '%s'") % source
       
    70 +                LOG.debug(msg)
       
    71 +                raise HTTPBadRequest(explanation=msg,
       
    72 +                                     request=req,
       
    73 +                                     content_type="text/plain")
       
    74  
       
    75      @staticmethod
       
    76      def _copy_from(req):
       
    77 --- glance-2013.2.3/glance/store/__init__.py.orig	2014-12-23 08:20:52.254600393 -0800
       
    78 +++ glance-2013.2.3/glance/store/__init__.py	2014-12-23 08:23:48.661399000 -0800
       
    79 @@ -21,6 +21,7 @@ import sys
       
    80  import time
       
    81  
       
    82  from oslo.config import cfg
       
    83 +import six.moves.urllib.parse as urlparse
       
    84  
       
    85  from glance.common import crypt
       
    86  from glance.common import exception
       
    87 @@ -369,6 +370,24 @@ def set_acls(context, location_uri, publ
       
    88          LOG.debug(_("Skipping store.set_acls... not implemented."))
       
    89  
       
    90  
       
    91 +def validate_external_location(uri):
       
    92 +    """
       
    93 +    Validate if URI of external location are supported.
       
    94 +
       
    95 +    Only over non-local store types are OK, i.e. S3, Swift,
       
    96 +    HTTP. Note the absence of 'file://' for security reasons,
       
    97 +    see LP bug #942118, 1400966, 'swift+config://' is also
       
    98 +    absent for security reasons, see LP bug #1334196.
       
    99 +
       
   100 +    :param uri: The URI of external image location.
       
   101 +    :return: Whether given URI of external image location are OK.
       
   102 +    """
       
   103 +    pieces = urlparse.urlparse(uri)
       
   104 +    valid_schemes = [scheme for scheme in location.SCHEME_TO_CLS_MAP.keys()
       
   105 +                     if scheme != 'file' and scheme != 'swift+config']
       
   106 +    return pieces.scheme in valid_schemes
       
   107 +
       
   108 +
       
   109  class ImageRepoProxy(glance.domain.proxy.Repo):
       
   110  
       
   111      def __init__(self, image_repo, context, store_api):
       
   112 @@ -401,22 +420,23 @@ class ImageRepoProxy(glance.domain.proxy
       
   113  
       
   114  
       
   115  def _check_location_uri(context, store_api, uri):
       
   116 -    """
       
   117 -    Check if an image location uri is valid.
       
   118 +    """Check if an image location is valid.
       
   119  
       
   120      :param context: Glance request context
       
   121      :param store_api: store API module
       
   122      :param uri: location's uri string
       
   123      """
       
   124 +
       
   125      is_ok = True
       
   126      try:
       
   127 -        size = store_api.get_size_from_backend(context, uri)
       
   128          # NOTE(zhiyan): Some stores return zero when it catch exception
       
   129 -        is_ok = size > 0
       
   130 +        is_ok = (store_api.validate_external_location(uri) and
       
   131 +                 store_api.get_size_from_backend(context, uri) > 0)
       
   132      except (exception.UnknownScheme, exception.NotFound):
       
   133          is_ok = False
       
   134      if not is_ok:
       
   135 -        raise exception.BadStoreUri(_('Invalid location: %s') % uri)
       
   136 +        reason = _('Invalid location')
       
   137 +        raise exception.BadStoreUri(message=reason)
       
   138  
       
   139  
       
   140  def _check_image_location(context, store_api, location):