CVE-2012-5571: Credentials Management Errors (CWE-255)
value: OpenStack Keystone Essex (2012.1) and Folsom (2012.2) does not properly handle EC2 tokens when the user role has been removed from a tenant, which allows remote authenticated users to bypass intended authorization restrictions by leveraging a token for the removed user role.
CWE description: Weaknesses in this category are related to the management of credentials.
Published: 2012-12-18T01:55Z
Repository: https://github.com/openstack/keystone
Language: Python
Files changed: keystone/contrib/ec2/core.py
Commit date: 2012-11-13 15:49:19 -0800
Commit message: Ensures User is member of tenant in ec2 validation

It is possible that a user is no longer a member of a tenant when
they attempt to use an ec2 token. This checks to make sure that
the user still has at least one valid role in the tenant before
authenticating them. This should automatically work for the s3
version as well since it is a subclass.

Fixes bug 1064914

Change-Id: Ieb237bae936a7b00ce7ba4d4c59aec6c7a69ec21

Diff: diff --git a/keystone/contrib/ec2/core.py b/keystone/contrib/ec2/core.py
index 5bf40103b..064474c7a 100644
--- a/keystone/contrib/ec2/core.py
+++ b/keystone/contrib/ec2/core.py
@@ -166,10 +166,20 @@ class Ec2Controller(wsgi.Application):
             user_id=creds_ref['user_id'])
         metadata_ref = self.identity_api.get_metadata(
             context=context,
             user_id=user_ref['id'],
             tenant_id=tenant_ref['id'])
+
+        # TODO(termie): optimize this call at some point and put it into the
+        #               the return for metadata
+        # fill out the roles in the metadata
+        roles = metadata_ref.get('roles', [])
+        if not roles:
+            raise exception.Unauthorized(message='User not valid for tenant.')
+        roles_ref = [self.identity_api.get_role(context, role_id)
+                     for role_id in roles]
+
         catalog_ref = self.catalog_api.get_catalog(
             context=context,
             user_id=user_ref['id'],
             tenant_id=tenant_ref['id'],
             metadata=metadata_ref)
@@ -178,17 +188,10 @@ class Ec2Controller(wsgi.Application):
             context, token_id, dict(id=token_id,
                                     user=user_ref,
                                     tenant=tenant_ref,
                                     metadata=metadata_ref))
 
-        # TODO(termie): optimize this call at some point and put it into the
-        #               the return for metadata
-        # fill out the roles in the metadata
-        roles_ref = []
-        for role_id in metadata_ref.get('roles', []):
-            roles_ref.append(self.identity_api.get_role(context, role_id))
-
         # TODO(termie): make this a util function or something
         # TODO(termie): i don't think the ec2 middleware currently expects a
         #               full return, but it contains a note saying that it
         #               would be better to expect a full return
         token_controller = service.TokenController()

Vulnerable code:         # TODO(termie): optimize this call at some point and put it into the
        #               the return for metadata
        # fill out the roles in the metadata
        roles_ref = []
        for role_id in metadata_ref.get('roles', []):
            roles_ref.append(self.identity_api.get_role(context, role_id))

Fixed code: 
        # TODO(termie): optimize this call at some point and put it into the
        #               the return for metadata
        # fill out the roles in the metadata
        roles = metadata_ref.get('roles', [])
        if not roles:
            raise exception.Unauthorized(message='User not valid for tenant.')
        roles_ref = [self.identity_api.get_role(context, role_id)
                     for role_id in roles]