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