prometheanfire    14/03/16 19:54:35

  Added:                2013.1.4-CVE-2014-2237.patch
                        2013.2.2-CVE-2014-2237.patch
  Log:
  fix for bug 503446 CVE-2014-2237
  
  (Portage version: 2.2.8-r1/cvs/Linux x86_64, signed Manifest commit with key 
0x2471eb3e40ac5ac3)

Revision  Changes    Path
1.1                  sys-auth/keystone/files/2013.1.4-CVE-2014-2237.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-auth/keystone/files/2013.1.4-CVE-2014-2237.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-auth/keystone/files/2013.1.4-CVE-2014-2237.patch?rev=1.1&content-type=text/plain

Index: 2013.1.4-CVE-2014-2237.patch
===================================================================
>From a411c944af78c36f2fdb87d305ba452dc52d7ed3 Mon Sep 17 00:00:00 2001
From: Morgan Fainberg <[email protected]>
Date: Fri, 21 Feb 2014 22:09:04 +0000
Subject: Ensure tokens are added to both Trustor and Trustee indexes

Tokens are now added to both the Trustor and Trustee user-token-index
so that bulk token revocations (e.g. password change) of the trustee
will work as expected. This is a backport of the basic code that was
used in the Icehouse-vintage Dogpile Token KVS backend that resolves
this issue by merging the handling of memcache and KVS backends into
the same logic.

Change-Id: I3e19e4a8fc1e11cef6db51d364e80061e97befa7
Closes-Bug: #1260080
---
diff --git a/keystone/token/backends/memcache.py 
b/keystone/token/backends/memcache.py
index c2c9b51..dc5c34e 100644
--- a/keystone/token/backends/memcache.py
+++ b/keystone/token/backends/memcache.py
@@ -62,6 +62,15 @@ class Token(token.Driver):
         return token_ref
 
     def create_token(self, token_id, data):
+
+        def update_index(user_id, token_data):
+            user_key = self._prefix_user_id(user_id)
+            if not self.client.append(user_key, ',%s' % token_data):
+                if not self.client.add(user_key, token_data):
+                    if not self.client.append(user_key, ',%s' % token_data):
+                        msg = _('Unable to add token user list.')
+                        raise exception.UnexpectedError(msg)
+
         data_copy = copy.deepcopy(data)
         ptk = self._prefix_token_id(token.unique_id(token_id))
         if not data_copy.get('expires'):
@@ -73,15 +82,19 @@ class Token(token.Driver):
             expires_ts = utils.unixtime(data_copy['expires'])
             kwargs['time'] = expires_ts
         self.client.set(ptk, data_copy, **kwargs)
+        token_data = jsonutils.dumps(token_id)
         if 'id' in data['user']:
-            token_data = jsonutils.dumps(token_id)
             user_id = data['user']['id']
-            user_key = self._prefix_user_id(user_id)
-            if not self.client.append(user_key, ',%s' % token_data):
-                if not self.client.add(user_key, token_data):
-                    if not self.client.append(user_key, ',%s' % token_data):
-                        msg = _('Unable to add token user list.')
-                        raise exception.UnexpectedError(msg)
+            update_index(user_id, token_data)
+
+        if CONF.trust.enabled and data.get('trust_id'):
+            if 'access' in data_copy:
+                trustee_user_id = data_copy['access']['trust'][
+                    'trustee_user_id']
+            else:
+                trustee_user_id = data_copy['OS-TRUST:trust'][
+                    'trustee_user_id']
+            update_index(trustee_user_id, token_data)
         return copy.deepcopy(data_copy)
 
     def _add_to_revocation_list(self, token_id, token_data):
diff --git a/tests/test_backend.py b/tests/test_backend.py
index 1af3c16..19caa0c 100644
--- a/tests/test_backend.py
+++ b/tests/test_backend.py
@@ -2096,7 +2096,8 @@ class TokenTests(object):
                           self.token_api.delete_token, token_id)
 
     def create_token_sample_data(self, tenant_id=None, trust_id=None,
-                                 user_id="testuserid"):
+                                 user_id='testuserid',
+                                 trustee_user_id='testuserid2'):
         token_id = self._create_token_id()
         data = {'id': token_id, 'a': 'b',
                 'user': {'id': user_id}}
@@ -2104,6 +2105,11 @@ class TokenTests(object):
             data['tenant'] = {'id': tenant_id, 'name': tenant_id}
         if trust_id is not None:
             data['trust_id'] = trust_id
+            data.setdefault('access', {}).setdefault('trust', {})
+            # Testuserid2 is used here since a trustee will be different in
+            # the cases of impersonation and therefore should not match the
+            # token's user_id.
+            data['access']['trust']['trustee_user_id'] = trustee_user_id
         self.token_api.create_token(token_id, data)
         return token_id
 
@@ -2290,6 +2296,39 @@ class TokenTests(object):
         for t in self.token_api.list_revoked_tokens():
             self.assertIn('expires', t)
 
+    def test_token_in_trustee_and_trustor_token_list(self):
+        self.opt_in_group('trust',
+                          enabled=True)
+        trustor = self.user_foo
+        trustee = self.user_two
+        trust_id = uuid.uuid4().hex
+        trust_info = {'trustor_user_id': trustor['id'],
+                      'trustee_user_id': trustee['id'],
+                      'project_id': self.tenant_bar['id'],
+                      'expires_at': timeutils.
+                      parse_isotime('2031-02-18T18:10:00Z'),
+                      'impersonation': True}
+        self.trust_api.create_trust(trust_id, trust_info,
+                                    roles=[{'id': 'member'},
+                                           {'id': 'other'},
+                                           {'id': 'browser'}])
+
+        token_id = self.create_token_sample_data(
+            tenant_id=self.tenant_bar['id'],
+            trust_id=trust_id,
+            user_id=trustor['id'],
+            trustee_user_id=trustee['id'])
+
+        # Ensure the token id exists in both the trustor and trustee token
+        # lists
+
+        self.assertIn(token_id,
+                      self.token_api.list_tokens(self.user_two['id'],
+                                                 trust_id=trust_id))
+        self.assertIn(token_id,
+                      self.token_api.list_tokens(self.user_foo['id'],
+                                                 trust_id=trust_id))
+
 
 class TrustTests(object):
     def create_sample_trust(self, new_id):
diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py
index f3a8ece..15a87b5 100644
--- a/tests/test_backend_kvs.py
+++ b/tests/test_backend_kvs.py
@@ -73,6 +73,8 @@ class KvsToken(test.TestCase, test_backend.TokenTests):
     def setUp(self):
         super(KvsToken, self).setUp()
         self.token_api = token_kvs.Token(db={})
+        self.load_backends()
+        self.load_fixtures(default_fixtures)
 
 
 class KvsTrust(test.TestCase, test_backend.TrustTests):
diff --git a/tests/test_backend_memcache.py b/tests/test_backend_memcache.py
index 9fbaeb9..6339e6f 100644
--- a/tests/test_backend_memcache.py
+++ b/tests/test_backend_memcache.py
@@ -18,6 +18,7 @@ import uuid
 
 import memcache
 
+import default_fixtures
 from keystone.common import utils
 from keystone.openstack.common import timeutils
 from keystone import test
@@ -75,8 +76,10 @@ class MemcacheClient(object):
 class MemcacheToken(test.TestCase, test_backend.TokenTests):
     def setUp(self):
         super(MemcacheToken, self).setUp()
+        self.load_backends()
         fake_client = MemcacheClient()
         self.token_api = token_memcache.Token(client=fake_client)
+        self.load_fixtures(default_fixtures)
 
     def test_create_unicode_token_id(self):
         token_id = unicode(self._create_token_id())
--
cgit v0.9.2



1.1                  sys-auth/keystone/files/2013.2.2-CVE-2014-2237.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-auth/keystone/files/2013.2.2-CVE-2014-2237.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-auth/keystone/files/2013.2.2-CVE-2014-2237.patch?rev=1.1&content-type=text/plain

Index: 2013.2.2-CVE-2014-2237.patch
===================================================================
>From b6f0e26da0e2ab0892a5658da281a065e668637b Mon Sep 17 00:00:00 2001
From: Morgan Fainberg <[email protected]>
Date: Fri, 21 Feb 2014 21:33:25 +0000
Subject: Ensure tokens are added to both Trustor and Trustee indexes

Tokens are now added to both the Trustor and Trustee user-token-index
so that bulk token revocations (e.g. password change) of the trustee
will work as expected. This is a backport of the basic code that was
used in the Icehouse-vintage Dogpile Token KVS backend that resolves
this issue by merging the handling of memcache and KVS backends into
the same logic.

Change-Id: I3e19e4a8fc1e11cef6db51d364e80061e97befa7
Closes-Bug: #1260080
---
diff --git a/keystone/tests/test_backend.py b/keystone/tests/test_backend.py
index e0e81ca..1e926c8 100644
--- a/keystone/tests/test_backend.py
+++ b/keystone/tests/test_backend.py
@@ -25,6 +25,7 @@ from keystone import exception
 from keystone.openstack.common import timeutils
 from keystone import tests
 from keystone.tests import default_fixtures
+from keystone.token import provider
 
 
 CONF = config.CONF
@@ -2645,7 +2646,8 @@ class TokenTests(object):
                           self.token_api.delete_token, token_id)
 
     def create_token_sample_data(self, tenant_id=None, trust_id=None,
-                                 user_id="testuserid"):
+                                 user_id='testuserid',
+                                 trustee_user_id='testuserid2'):
         token_id = self._create_token_id()
         data = {'id': token_id, 'a': 'b',
                 'user': {'id': user_id}}
@@ -2655,6 +2657,15 @@ class TokenTests(object):
             data['tenant'] = None
         if trust_id is not None:
             data['trust_id'] = trust_id
+            data.setdefault('access', {}).setdefault('trust', {})
+            # Testuserid2 is used here since a trustee will be different in
+            # the cases of impersonation and therefore should not match the
+            # token's user_id.
+            data['access']['trust']['trustee_user_id'] = trustee_user_id
+        data['token_version'] = provider.V2
+        # Issue token stores a copy of all token data at token['token_data'].
+        # This emulates that assumption as part of the test.
+        data['token_data'] = copy.deepcopy(data)
         new_token = self.token_api.create_token(token_id, data)
         return new_token['id']
 
@@ -2907,6 +2918,39 @@ class TokenTests(object):
         for t in self.token_api.list_revoked_tokens():
             self.assertIn('expires', t)
 
+    def test_token_in_trustee_and_trustor_token_list(self):
+        self.opt_in_group('trust',
+                          enabled=True)
+        trustor = self.user_foo
+        trustee = self.user_two
+        trust_id = uuid.uuid4().hex
+        trust_info = {'trustor_user_id': trustor['id'],
+                      'trustee_user_id': trustee['id'],
+                      'project_id': self.tenant_bar['id'],
+                      'expires_at': timeutils.
+                      parse_isotime('2031-02-18T18:10:00Z'),
+                      'impersonation': True}
+        self.trust_api.create_trust(trust_id, trust_info,
+                                    roles=[{'id': 'member'},
+                                           {'id': 'other'},
+                                           {'id': 'browser'}])
+
+        token_id = self.create_token_sample_data(
+            tenant_id=self.tenant_bar['id'],
+            trust_id=trust_id,
+            user_id=trustor['id'],
+            trustee_user_id=trustee['id'])
+
+        # Ensure the token id exists in both the trustor and trustee token
+        # lists
+
+        self.assertIn(token_id,
+                      self.token_api.list_tokens(self.user_two['id'],
+                                                 trust_id=trust_id))
+        self.assertIn(token_id,
+                      self.token_api.list_tokens(self.user_foo['id'],
+                                                 trust_id=trust_id))
+
 
 class TokenCacheInvalidation(object):
     def _create_test_data(self):
diff --git a/keystone/tests/test_backend_kvs.py 
b/keystone/tests/test_backend_kvs.py
index ac9df71..a23882c 100644
--- a/keystone/tests/test_backend_kvs.py
+++ b/keystone/tests/test_backend_kvs.py
@@ -70,6 +70,7 @@ class KvsToken(tests.TestCase, test_backend.TokenTests):
         identity.CONF.identity.driver = (
             'keystone.identity.backends.kvs.Identity')
         self.load_backends()
+        self.load_fixtures(default_fixtures)
 
 
 class KvsTrust(tests.TestCase, test_backend.TrustTests):
diff --git a/keystone/tests/test_backend_memcache.py 
b/keystone/tests/test_backend_memcache.py
index 964d5b4..c99a6a3 100644
--- a/keystone/tests/test_backend_memcache.py
+++ b/keystone/tests/test_backend_memcache.py
@@ -26,6 +26,7 @@ from keystone import exception
 from keystone.openstack.common import jsonutils
 from keystone.openstack.common import timeutils
 from keystone import tests
+from keystone.tests import default_fixtures
 from keystone.tests import test_backend
 from keystone.tests import test_utils
 from keystone import token
@@ -115,6 +116,7 @@ class MemcacheToken(tests.TestCase, 
test_backend.TokenTests):
     def setUp(self):
         super(MemcacheToken, self).setUp()
         self.load_backends()
+        self.load_fixtures(default_fixtures)
         fake_client = MemcacheClient()
         self.token_man = token.Manager()
         self.token_man.driver = token_memcache.Token(client=fake_client)
diff --git a/keystone/token/backends/kvs.py b/keystone/token/backends/kvs.py
index b3f991a..c0d6e36 100644
--- a/keystone/token/backends/kvs.py
+++ b/keystone/token/backends/kvs.py
@@ -150,5 +150,7 @@ class Token(kvs.Base, token.Driver):
     def flush_expired_tokens(self):
         now = timeutils.utcnow()
         for token, token_ref in self.db.items():
+            if not token.startswith('revoked-token-'):
+                continue
             if self.is_expired(now, token_ref):
                 self.db.delete(token)
diff --git a/keystone/token/backends/memcache.py 
b/keystone/token/backends/memcache.py
index a6fe826..08c1c40 100644
--- a/keystone/token/backends/memcache.py
+++ b/keystone/token/backends/memcache.py
@@ -83,12 +83,33 @@ class Token(token.Driver):
             expires_ts = utils.unixtime(data_copy['expires'])
             kwargs['time'] = expires_ts
         self.client.set(ptk, data_copy, **kwargs)
-        if 'id' in data['user']:
-            user_id = data['user']['id']
-            user_key = self._prefix_user_id(user_id)
-            # Append the new token_id to the token-index-list stored in the
-            # user-key within memcache.
-            self._update_user_list_with_cas(user_key, token_id, data_copy)
+        user_id = data['user']['id']
+        user_key = self._prefix_user_id(user_id)
+        # Append the new token_id to the token-index-list stored in the
+        # user-key within memcache.
+        self._update_user_list_with_cas(user_key, token_id, data_copy)
+        if CONF.trust.enabled and data.get('trust_id'):
+            # NOTE(morganfainberg): If trusts are enabled and this is a trust
+            # scoped token, we add the token to the trustee list as well.  This
+            # allows password changes of the trustee to also expire the token.
+            # There is no harm in placing the token in multiple lists, as
+            # _list_tokens is smart enough to handle almost any case of
+            # valid/invalid/expired for a given token.
+            token_data = data_copy['token_data']
+            if data_copy['token_version'] == token.provider.V2:
+                trustee_user_id = token_data['access']['trust'][
+                    'trustee_user_id']
+            elif data_copy['token_version'] == token.provider.V3:
+                trustee_user_id = token_data['OS-TRUST:trust'][
+                    'trustee_user_id']
+            else:
+                raise token.provider.UnsupportedTokenVersionException(
+                    _('Unknown token version %s') %
+                    data_copy.get('token_version'))
+
+            trustee_key = self._prefix_user_id(trustee_user_id)
+            self._update_user_list_with_cas(trustee_key, token_id, data_copy)
+
         return copy.deepcopy(data_copy)
 
     def _convert_user_index_from_json(self, token_list, user_key):
--
cgit v0.9.2




Reply via email to