From e378062bd99d3d59fc9ce82ba3c8f240c137e6a9 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 18 Aug 2016 14:00:53 +0300 Subject: [PATCH] 403 Forbidden returned if the permission error occurred on listing requested folder Related: #921 --- aiohttp/web_urldispatcher.py | 5 ++++- tests/test_web_urldispatcher.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 6a605bb6532..ea908ddd088 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -495,7 +495,10 @@ def handle(self, request): # on opening a dir, load it's contents if allowed if filepath.is_dir(): if self._show_index: - ret = Response(text=self._directory_as_html(filepath)) + try: + ret = Response(text=self._directory_as_html(filepath)) + except PermissionError: + raise HTTPForbidden() else: raise HTTPForbidden() elif filepath.is_file(): diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py index 2ba9467278e..46058c1e458 100644 --- a/tests/test_web_urldispatcher.py +++ b/tests/test_web_urldispatcher.py @@ -11,6 +11,9 @@ from aiohttp.web import HTTPCreated, Response from aiohttp.web_urldispatcher import PlainRoute, SystemRoute, UrlDispatcher +from unittest import mock +from unittest.mock import MagicMock + @pytest.fixture(scope='function') def tmp_dir_path(request): @@ -91,6 +94,35 @@ def test_access_non_existing_resource(tmp_dir_path, create_app_and_client): yield from r.release() +@pytest.mark.run_loop +def test_unauthorized_folder_access(tmp_dir_path, create_app_and_client): + """ + Tests the unauthorized access to a folder of static file server. + Try to list a folder content of static file server when server does not + have permissions to do so for the folder. + """ + my_dir_path = os.path.join(tmp_dir_path, 'my_dir') + os.mkdir(my_dir_path) + + app, client = yield from create_app_and_client() + + with mock.patch('pathlib.Path.__new__') as path_constructor: + path = MagicMock() + path.joinpath.return_value = path + path.resolve.return_value = path + path.iterdir.return_value.__iter__.side_effect = PermissionError() + path_constructor.return_value = path + + # Register global static route: + app.router.add_static('/', tmp_dir_path, show_index=True) + + # Request the root of the static directory. + r = yield from client.get('/my_dir') + assert r.status == 403 + + yield from r.release() + + @pytest.mark.run_loop def test_partialy_applied_handler(create_app_and_client): app, client = yield from create_app_and_client()