summaryrefslogtreecommitdiff
path: root/sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch
diff options
context:
space:
mode:
authorMatthew Thode <prometheanfire@gentoo.org>2016-02-02 10:01:35 -0600
committerMatthew Thode <prometheanfire@gentoo.org>2016-02-02 10:09:17 -0600
commitab7179f257e6dd899085f66fc81bb6a79418eb05 (patch)
tree1e61129012867afee90937bed75990aec7b0f06d /sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch
parenta2ce168aefeb329c24c770e041663eaeaefc725e (diff)
downloadgentoo-ab7179f257e6dd899085f66fc81bb6a79418eb05.tar.gz
gentoo-ab7179f257e6dd899085f66fc81bb6a79418eb05.tar.xz
sys-auth/keystone: fixing bug 573658 CVE-2015-7546
Package-Manager: portage-2.2.26
Diffstat (limited to 'sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch')
-rw-r--r--sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch216
1 files changed, 216 insertions, 0 deletions
diff --git a/sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch b/sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch
new file mode 100644
index 00000000000..82bff1edbe9
--- /dev/null
+++ b/sys-auth/keystone/files/CVE-2015-7546_8.0.1.patch
@@ -0,0 +1,216 @@
+From bff03b5726fe5cac93d44a66715eea49b89c8cb0 Mon Sep 17 00:00:00 2001
+From: Brant Knudson <bknudson@us.ibm.com>
+Date: Tue, 1 Dec 2015 11:09:14 -0600
+Subject: [PATCH] Add audit IDs to revocation events
+
+The revoked tokens' audit ID is now included in the data returned in
+the revocation list.
+
+Closes-Bug: 1490804
+Change-Id: Ifcf88f1158bebddc4f927121fbf4136fb53b659f
+(cherry picked from commit d5378f173da14a34ca010271477337879002d6d0)
+Conflicts:
+ keystone/tests/unit/test_backend.py
+---
+ keystone/tests/unit/test_backend.py | 39 ++++++++++++++--------
+ keystone/tests/unit/test_backend_sql.py | 3 +-
+ keystone/token/persistence/backends/kvs.py | 9 +++++
+ keystone/token/persistence/backends/sql.py | 12 ++++++-
+ .../notes/bug-1490804-de58a9606edb31eb.yaml | 13 ++++++++
+ 5 files changed, 61 insertions(+), 15 deletions(-)
+ create mode 100644 releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml
+
+diff --git a/keystone/tests/unit/test_backend.py b/keystone/tests/unit/test_backend.py
+index 2340645..1273736 100644
+--- a/keystone/tests/unit/test_backend.py
++++ b/keystone/tests/unit/test_backend.py
+@@ -4426,7 +4426,9 @@ class TokenTests(object):
+ token_id = self._create_token_id()
+ data = {'id': token_id, 'a': 'b',
+ 'trust_id': None,
+- 'user': {'id': 'testuserid'}}
++ 'user': {'id': 'testuserid'},
++ 'token_data': {'access': {'token': {
++ 'audit_ids': [uuid.uuid4().hex]}}}}
+ data_ref = self.token_provider_api._persistence.create_token(token_id,
+ data)
+ expires = data_ref.pop('expires')
+@@ -4461,7 +4463,8 @@ class TokenTests(object):
+ # FIXME(morganfainberg): These tokens look nothing like "Real" tokens.
+ # This should be fixed when token issuance is cleaned up.
+ data = {'id': token_id, 'a': 'b',
+- 'user': {'id': user_id}}
++ 'user': {'id': user_id},
++ 'access': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
+ if tenant_id is not None:
+ data['tenant'] = {'id': tenant_id, 'name': tenant_id}
+ if tenant_id is NULL_OBJECT:
+@@ -4470,7 +4473,7 @@ class TokenTests(object):
+ data['expires'] = expires
+ if trust_id is not None:
+ data['trust_id'] = trust_id
+- data.setdefault('access', {}).setdefault('trust', {})
++ data['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.
+@@ -4633,17 +4636,21 @@ class TokenTests(object):
+
+ self.assertEqual(data_ref, new_data_ref)
+
+- def check_list_revoked_tokens(self, token_ids):
+- revoked_ids = [x['id']
+- for x in self.token_provider_api.list_revoked_tokens()]
++ def check_list_revoked_tokens(self, token_infos):
++ revocation_list = self.token_provider_api.list_revoked_tokens()
++ revoked_ids = [x['id'] for x in revocation_list]
++ revoked_audit_ids = [x['audit_id'] for x in revocation_list]
+ self._assert_revoked_token_list_matches_token_persistence(revoked_ids)
+- for token_id in token_ids:
++ for token_id, audit_id in token_infos:
+ self.assertIn(token_id, revoked_ids)
++ self.assertIn(audit_id, revoked_audit_ids)
+
+ def delete_token(self):
+ token_id = uuid.uuid4().hex
++ audit_id = uuid.uuid4().hex
+ data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
+- 'user': {'id': 'testuserid'}}
++ 'user': {'id': 'testuserid'},
++ 'token_data': {'token': {'audit_ids': [audit_id]}}}
+ data_ref = self.token_provider_api._persistence.create_token(token_id,
+ data)
+ self.token_provider_api._persistence.delete_token(token_id)
+@@ -4655,7 +4662,7 @@ class TokenTests(object):
+ exception.TokenNotFound,
+ self.token_provider_api._persistence.delete_token,
+ data_ref['id'])
+- return token_id
++ return (token_id, audit_id)
+
+ def test_list_revoked_tokens_returns_empty_list(self):
+ revoked_ids = [x['id']
+@@ -4706,12 +4713,16 @@ class TokenTests(object):
+ token_data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
+ 'expires': expire_time,
+ 'trust_id': None,
+- 'user': {'id': 'testuserid'}}
++ 'user': {'id': 'testuserid'},
++ 'token_data': {'token': {
++ 'audit_ids': [uuid.uuid4().hex]}}}
+ token2_id = uuid.uuid4().hex
+ token2_data = {'id_hash': token2_id, 'id': token2_id, 'a': 'b',
+ 'expires': expire_time,
+ 'trust_id': None,
+- 'user': {'id': 'testuserid'}}
++ 'user': {'id': 'testuserid'},
++ 'token_data': {'token': {
++ 'audit_ids': [uuid.uuid4().hex]}}}
+ # Create 2 Tokens.
+ self.token_provider_api._persistence.create_token(token_id,
+ token_data)
+@@ -4746,7 +4757,8 @@ class TokenTests(object):
+ def _test_predictable_revoked_pki_token_id(self, hash_fn):
+ token_id = self._create_token_id()
+ token_id_hash = hash_fn(token_id).hexdigest()
+- token = {'user': {'id': uuid.uuid4().hex}}
++ token = {'user': {'id': uuid.uuid4().hex},
++ 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
+
+ self.token_provider_api._persistence.create_token(token_id, token)
+ self.token_provider_api._persistence.delete_token(token_id)
+@@ -4768,7 +4780,8 @@ class TokenTests(object):
+
+ def test_predictable_revoked_uuid_token_id(self):
+ token_id = uuid.uuid4().hex
+- token = {'user': {'id': uuid.uuid4().hex}}
++ token = {'user': {'id': uuid.uuid4().hex},
++ 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
+
+ self.token_provider_api._persistence.create_token(token_id, token)
+ self.token_provider_api._persistence.delete_token(token_id)
+diff --git a/keystone/tests/unit/test_backend_sql.py b/keystone/tests/unit/test_backend_sql.py
+index 69fac63..51221a3 100644
+--- a/keystone/tests/unit/test_backend_sql.py
++++ b/keystone/tests/unit/test_backend_sql.py
+@@ -492,7 +492,8 @@ class SqlToken(SqlTests, test_backend.TokenTests):
+ # necessary.
+
+ expected_query_args = (token_sql.TokenModel.id,
+- token_sql.TokenModel.expires)
++ token_sql.TokenModel.expires,
++ token_sql.TokenModel.extra,)
+
+ with mock.patch.object(token_sql, 'sql') as mock_sql:
+ tok = token_sql.Token()
+diff --git a/keystone/token/persistence/backends/kvs.py b/keystone/token/persistence/backends/kvs.py
+index 5193158..60f7931 100644
+--- a/keystone/token/persistence/backends/kvs.py
++++ b/keystone/token/persistence/backends/kvs.py
+@@ -210,6 +210,15 @@ class Token(token.persistence.TokenDriverV8):
+ subsecond=True)
+ revoked_token_data['id'] = data['id']
+
++ token_data = data['token_data']
++ if 'access' in token_data:
++ # It's a v2 token.
++ audit_ids = token_data['access']['token']['audit_ids']
++ else:
++ # It's a v3 token.
++ audit_ids = token_data['token']['audit_ids']
++ revoked_token_data['audit_id'] = audit_ids[0]
++
+ token_list = self._get_key_or_default(self.revocation_key, default=[])
+ if not isinstance(token_list, list):
+ # NOTE(morganfainberg): In the case that the revocation list is not
+diff --git a/keystone/token/persistence/backends/sql.py b/keystone/token/persistence/backends/sql.py
+index 6fc1d22..d677620 100644
+--- a/keystone/token/persistence/backends/sql.py
++++ b/keystone/token/persistence/backends/sql.py
+@@ -228,13 +228,23 @@ class Token(token.persistence.TokenDriverV8):
+ session = sql.get_session()
+ tokens = []
+ now = timeutils.utcnow()
+- query = session.query(TokenModel.id, TokenModel.expires)
++ query = session.query(TokenModel.id, TokenModel.expires,
++ TokenModel.extra)
+ query = query.filter(TokenModel.expires > now)
+ token_references = query.filter_by(valid=False)
+ for token_ref in token_references:
++ token_data = token_ref[2]['token_data']
++ if 'access' in token_data:
++ # It's a v2 token.
++ audit_ids = token_data['access']['token']['audit_ids']
++ else:
++ # It's a v3 token.
++ audit_ids = token_data['token']['audit_ids']
++
+ record = {
+ 'id': token_ref[0],
+ 'expires': token_ref[1],
++ 'audit_id': audit_ids[0],
+ }
+ tokens.append(record)
+ return tokens
+diff --git a/releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml b/releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml
+new file mode 100644
+index 0000000..0d5c203
+--- /dev/null
++++ b/releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml
+@@ -0,0 +1,13 @@
++---
++features:
++ - >
++ [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
++ Audit IDs are included in the token revocation list.
++security:
++ - >
++ [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
++ [`CVE-2015-7546 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-7546>`_]
++ A bug is fixed where an attacker could avoid token revocation when the PKI
++ or PKIZ token provider is used. The complete remediation for this
++ vulnerability requires the corresponding fix in the keystonemiddleware
++ project.
+--
+1.9.1
+