From 6b3b7296b997d83bf272abc78581c6afb5d4131e Mon Sep 17 00:00:00 2001 From: Gleb Stepanov Date: Fri, 22 Jul 2016 18:37:48 +0300 Subject: [PATCH] Skip malformed cookies Skip malformed cookies when parsing Cookie header in websocketproxy.py. Change-Id: I4091bd641ca3911666da328488c337835405400f Closes-Bug: #1496932 --- nova/console/websocketproxy.py | 15 ++++++++-- .../tests/unit/console/test_websocketproxy.py | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/nova/console/websocketproxy.py b/nova/console/websocketproxy.py index 6a7b1ec71039..f9bb39b3389d 100644 --- a/nova/console/websocketproxy.py +++ b/nova/console/websocketproxy.py @@ -31,6 +31,7 @@ from nova.consoleauth import rpcapi as consoleauth_rpcapi from nova import context from nova import exception from nova.i18n import _ +from nova.i18n import _LW LOG = logging.getLogger(__name__) @@ -88,9 +89,17 @@ class NovaProxyRequestHandlerBase(object): hcookie = self.headers.getheader('cookie') if hcookie: cookie = Cookie.SimpleCookie() - cookie.load(hcookie) - if 'token' in cookie: - token = cookie['token'].value + for hcookie_part in hcookie.split(';'): + hcookie_part = hcookie_part.lstrip() + try: + cookie.load(hcookie_part) + except Cookie.CookieError: + # NOTE(stgleb): Do not print out cookie content + # for security reasons. + LOG.warning(_LW('Found malformed cookie')) + else: + if 'token' in cookie: + token = cookie['token'].value ctxt = context.get_admin_context() rpcapi = consoleauth_rpcapi.ConsoleAuthAPI() diff --git a/nova/tests/unit/console/test_websocketproxy.py b/nova/tests/unit/console/test_websocketproxy.py index 1e7e306dcfa4..ad4045aae165 100644 --- a/nova/tests/unit/console/test_websocketproxy.py +++ b/nova/tests/unit/console/test_websocketproxy.py @@ -115,6 +115,16 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase): else: return + def _fake_getheader_malformed_cookie(self, header): + if header == 'cookie': + return '?=!; token="123-456-789"' + elif header == 'Origin': + return 'https://example.net:6080' + elif header == 'Host': + return 'example.net:6080' + else: + return + @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token') def test_new_websocket_client(self, check_token): check_token.return_value = { @@ -370,3 +380,21 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase): self.assertRaises(exception.ValidationError, self.wh.new_websocket_client) + + @mock.patch('nova.consoleauth.rpcapi.ConsoleAuthAPI.check_token') + def test_malformed_cookie(self, check_token): + check_token.return_value = { + 'host': 'node1', + 'port': '10000', + 'console_type': 'novnc', + 'access_url': 'https://example.net:6080' + } + self.wh.socket.return_value = '' + self.wh.path = "http://127.0.0.1/" + self.wh.headers.getheader = self._fake_getheader_malformed_cookie + + self.wh.new_websocket_client() + + check_token.assert_called_with(mock.ANY, token="123-456-789") + self.wh.socket.assert_called_with('node1', 10000, connect=True) + self.wh.do_proxy.assert_called_with('')