CVE-2012-3426: Permissions, Privileges, and Access Controls (CWE-264)
value: OpenStack Keystone before 2012.1.1, as used in OpenStack Folsom before Folsom-1 and OpenStack Essex, does not properly implement token expiration, which allows remote authenticated users to bypass intended authorization restrictions by (1) creating new tokens through token chaining, (2) leveraging possession of a token for a disabled user account, or (3) leveraging possession of a token for an account with a changed password.
CWE description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Published: 2012-07-31T10:45Z
Repository: https://github.com/openstack/keystone
Language: Python
Files changed: keystone/service.py, tests/test_keystoneclient.py
Commit date: 2012-06-05 15:27:13 +0100
Commit message: Carrying over token expiry time when token chaining

Fixes bug #998185

This commit causes the token expiry time to be maintained when
one token is being created from another

Change-Id: I7b61692a60d9227423b93c267864a5abe939ca33

Diff: diff --git a/keystone/service.py b/keystone/service.py
index 2b024f4e..ebdea50a 100644
--- a/keystone/service.py
+++ b/keystone/service.py
@@ -349,11 +349,12 @@ class TokenController(wsgi.Application):
 
             token_ref = self.token_api.create_token(
                     context, token_id, dict(id=token_id,
                                             user=user_ref,
                                             tenant=tenant_ref,
-                                            metadata=metadata_ref))
+                                            metadata=metadata_ref,
+                                            expires=old_token_ref['expires']))
 
         # 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 = []
diff --git a/tests/test_keystoneclient.py b/tests/test_keystoneclient.py
index 68f190fa..dc26c959 100644
--- a/tests/test_keystoneclient.py
+++ b/tests/test_keystoneclient.py
@@ -12,10 +12,11 @@
 # 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 nose.exc
 
 from keystone import test
@@ -331,10 +332,21 @@ class KeystoneClientTests(object):
 
         self.assertRaises(client_exceptions.Unauthorized,
                           self.get_client,
                           self.user_foo)
 
+    def test_token_expiry_maintained(self):
+        foo_client = self.get_client(self.user_foo)
+        orig_token = foo_client.service_catalog.catalog['token']
+
+        time.sleep(1.01)
+        reauthenticated_token = foo_client.tokens.authenticate(
+                                    token=foo_client.auth_token)
+
+        self.assertEquals(orig_token['expires'],
+                          reauthenticated_token.expires)
+
     def test_user_create_update_delete(self):
         from keystoneclient import exceptions as client_exceptions
 
         test_username = 'new_user'
         client = self.get_client(admin=True)

Vulnerable code:                                             metadata=metadata_ref))
Fixed code:                                             metadata=metadata_ref,
                                            expires=old_token_ref['expires']))
import time
    def test_token_expiry_maintained(self):
        foo_client = self.get_client(self.user_foo)
        orig_token = foo_client.service_catalog.catalog['token']

        time.sleep(1.01)
        reauthenticated_token = foo_client.tokens.authenticate(
                                    token=foo_client.auth_token)

        self.assertEquals(orig_token['expires'],
                          reauthenticated_token.expires)