CVE-2012-5563: Credentials Management Errors (CWE-255)
value: OpenStack Keystone, as used in OpenStack Folsom 2012.2, does not properly implement token expiration, which allows remote authenticated users to bypass intended authorization restrictions by creating new tokens through token chaining.  NOTE: this issue exists because of a CVE-2012-3426 regression.
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/service.py, tests/test_service.py
Commit date: 2012-11-28 10:28:07 -0500
Commit message: Ensure token expiration is maintained (bug 1079216)

Change-Id: I95853ec36e9c4cd937cfac7e08b648e830f9efd0

Diff: diff --git a/keystone/service.py b/keystone/service.py
index 90b44562f..808fb91f1 100644
--- a/keystone/service.py
+++ b/keystone/service.py
@@ -528,10 +528,11 @@ class TokenController(wsgi.Application):
                 config.CONF.signing.token_format)
         try:
             self.token_api.create_token(
                 context, token_id, dict(key=token_id,
                                         id=token_id,
+                                        expires=auth_token_data['expires'],
                                         user=user_ref,
                                         tenant=tenant_ref,
                                         metadata=metadata_ref))
         except Exception as e:
             # an identical token may have been created already.
diff --git a/tests/test_service.py b/tests/test_service.py
index 088d222b5..c256e7e03 100644
--- a/tests/test_service.py
+++ b/tests/test_service.py
@@ -10,22 +10,27 @@
 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import time
 import uuid
 
 import default_fixtures
 
+from keystone import config
 from keystone import exception
 from keystone import identity
 from keystone import service
 from keystone import test
 from keystone.identity.backends import kvs as kvs_identity
 from keystone.openstack.common import timeutils
 
 
+CONF = config.CONF
+
+
 def _build_user_auth(token=None, username=None,
                      password=None, tenant_name=None):
     """Build auth dictionary.
 
     It will create an auth dictionary based on all the arguments
@@ -294,5 +299,57 @@ class AuthWithRemoteUser(TokenControllerTest):
         self.assertRaises(
             exception.Unauthorized,
             self.api.authenticate,
             {'REMOTE_USER': uuid.uuid4().hex},
             body_dict)
+
+
+class TokenExpirationTest(test.TestCase):
+    def setUp(self):
+        super(TokenExpirationTest, self).setUp()
+        self.identity_api = kvs_identity.Identity()
+        self.load_fixtures(default_fixtures)
+        self.api = service.TokenController()
+
+    def _maintain_token_expiration(self):
+        """Token expiration should be maintained after re-auth & validation."""
+        r = self.api.authenticate(
+            {},
+            auth={
+                'passwordCredentials': {
+                    'username': self.user_foo['name'],
+                    'password': self.user_foo['password']
+                }
+            })
+        unscoped_token_id = r['access']['token']['id']
+        original_expiration = r['access']['token']['expires']
+
+        time.sleep(0.5)
+
+        r = self.api.validate_token(
+            dict(is_admin=True, query_string={}),
+            token_id=unscoped_token_id)
+        self.assertEqual(original_expiration, r['access']['token']['expires'])
+
+        time.sleep(0.5)
+
+        r = self.api.authenticate(
+            {},
+            auth={
+                'token': {
+                    'id': unscoped_token_id,
+                },
+                'tenantId': self.tenant_bar['id'],
+            })
+        scoped_token_id = r['access']['token']['id']
+        self.assertEqual(original_expiration, r['access']['token']['expires'])
+
+        time.sleep(0.5)
+
+        r = self.api.validate_token(
+            dict(is_admin=True, query_string={}),
+            token_id=scoped_token_id)
+        self.assertEqual(original_expiration, r['access']['token']['expires'])
+
+    def test_maintain_uuid_token_expiration(self):
+        self.opt_in_group('signing', token_format='UUID')
+        self._maintain_token_expiration()

Fixed code:                                         expires=auth_token_data['expires'],
import time
from keystone import config
CONF = config.CONF




class TokenExpirationTest(test.TestCase):
    def setUp(self):
        super(TokenExpirationTest, self).setUp()
        self.identity_api = kvs_identity.Identity()
        self.load_fixtures(default_fixtures)
        self.api = service.TokenController()

    def _maintain_token_expiration(self):
        """Token expiration should be maintained after re-auth & validation."""
        r = self.api.authenticate(
            {},
            auth={
                'passwordCredentials': {
                    'username': self.user_foo['name'],
                    'password': self.user_foo['password']
                }
            })
        unscoped_token_id = r['access']['token']['id']
        original_expiration = r['access']['token']['expires']

        time.sleep(0.5)

        r = self.api.validate_token(
            dict(is_admin=True, query_string={}),
            token_id=unscoped_token_id)
        self.assertEqual(original_expiration, r['access']['token']['expires'])

        time.sleep(0.5)

        r = self.api.authenticate(
            {},
            auth={
                'token': {
                    'id': unscoped_token_id,
                },
                'tenantId': self.tenant_bar['id'],
            })
        scoped_token_id = r['access']['token']['id']
        self.assertEqual(original_expiration, r['access']['token']['expires'])

        time.sleep(0.5)

        r = self.api.validate_token(
            dict(is_admin=True, query_string={}),
            token_id=scoped_token_id)
        self.assertEqual(original_expiration, r['access']['token']['expires'])

    def test_maintain_uuid_token_expiration(self):
        self.opt_in_group('signing', token_format='UUID')
        self._maintain_token_expiration()