CVE-2012-4457 (published 2012-10-09T15:55Z)

OpenStack Keystone Essex before 2012.1.2 and Folsom before folsom-3 does not properly handle authorization tokens for disabled tenants, which allows remote authenticated users to access the tenant's resources by requesting a token for the tenant.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:P/I:N/A:N)

Weakness information:
cwe_id: CWE-287
cwe_name: Improper Authentication
description: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
extended_description: 
            
			
         
         

Fix information:
repo_url: https://github.com/openstack/keystone
commit_details: repo_url: https://github.com/openstack/keystone
author: Dolph Mathews
author_date: 2012-07-16 16:08:32-05:00
msg: Raise unauthorized if tenant disabled (bug 988920)

If the client attempts to explicitly authenticate against a disabled
tenant, keystone should return HTTP 401 Unauthorized.

Change-Id: I49fe56b6ef8d9f2fc6b9357472dae8964bb9cb9c
repository: repo_url: https://github.com/openstack/keystone
repo_name: openstack/keystone
description: OpenStack Identity (Keystone). Mirror of code maintained at opendev.org.
repo_language: Python
owner: openstack
file_changes: filename: service.py
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@ import routes
 
 from keystone import catalog
 from keystone.common import logging
-from keystone.common import utils
 from keystone.common import wsgi
 from keystone import exception
 from keystone import identity
@@ -284,6 +283,11 @@ class TokenController(wsgi.Application):
                 if not user_ref.get('enabled', True):
                     LOG.warning('User %s is disabled' % user_id)
                     raise exception.Unauthorized()
+
+                # If the tenant is disabled don't allow them to authenticate
+                if tenant_ref and not tenant_ref.get('enabled', True):
+                    LOG.warning('Tenant %s is disabled' % tenant_id)
+                    raise exception.Unauthorized()
             except AssertionError as e:
                 raise exception.Unauthorized(e.message)
 
@@ -354,6 +358,14 @@ class TokenController(wsgi.Application):
                 tenant_ref = None
                 metadata_ref = {}
                 catalog_ref = {}
+            except exception.MetadataNotFound:
+                metadata_ref = {}
+                catalog_ref = {}
+
+            # If the tenant is disabled don't allow them to authenticate
+            if tenant_ref and not tenant_ref.get('enabled', True):
+                LOG.warning('Tenant %s is disabled' % tenant_id)
+                raise exception.Unauthorized()
 
             token_ref = self.token_api.create_token(
                 context, token_id, dict(id=token_id,

programming_language: Python
filename: test_keystoneclient.py
change_type: ModificationType.MODIFY
diff: @@ -180,6 +180,53 @@ class KeystoneClientTests(object):
                           self.get_client,
                           user_ref)
 
+    def test_authenticate_disabled_tenant(self):
+        from keystoneclient import exceptions as client_exceptions
+
+        admin_client = self.get_client(admin=True)
+
+        tenant = {
+            'name': uuid.uuid4().hex,
+            'description': uuid.uuid4().hex,
+            'enabled': False,
+        }
+        tenant_ref = admin_client.tenants.create(
+            tenant_name=tenant['name'],
+            description=tenant['description'],
+            enabled=tenant['enabled'])
+        tenant['id'] = tenant_ref.id
+
+        user = {
+            'name': uuid.uuid4().hex,
+            'password': uuid.uuid4().hex,
+            'email': uuid.uuid4().hex,
+            'tenant_id': tenant['id'],
+        }
+        user_ref = admin_client.users.create(
+            name=user['name'],
+            password=user['password'],
+            email=user['email'],
+            tenant_id=user['tenant_id'])
+        user['id'] = user_ref.id
+
+        # password authentication
+        self.assertRaises(
+            client_exceptions.Unauthorized,
+            self._client,
+            username=user['name'],
+            password=user['password'],
+            tenant_id=tenant['id'])
+
+        # token authentication
+        client = self._client(
+            username=user['name'],
+            password=user['password'])
+        self.assertRaises(
+            client_exceptions.Unauthorized,
+            self._client,
+            token=client.auth_token,
+            tenant_id=tenant['id'])
+
     # FIXME(ja): this test should require the "keystone:admin" roled
     #            (probably the role set via --keystone_admin_role flag)
     # FIXME(ja): add a test that admin endpoint is only sent to admin user

programming_language: Python