mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 04:20:14 +03:00
test: add tests for unvalidated symlink creation in import_project
This commit is contained in:
parent
a225622a6e
commit
b797981a65
@ -169,7 +169,11 @@ async def import_project(
|
||||
|
||||
def _create_symbolic_links(zip_file, path):
|
||||
"""
|
||||
Materialise symlink entries, refusing any target that escapes `path`.
|
||||
Manually create symbolic links (if any) because ZipFile does not support it.
|
||||
Refuse any target that escapes `path`.
|
||||
|
||||
:param zip_file: ZipFile instance
|
||||
:param path: project location
|
||||
"""
|
||||
|
||||
path_root = os.path.realpath(path) + os.sep
|
||||
|
||||
@ -19,6 +19,8 @@ import os
|
||||
import uuid
|
||||
import json
|
||||
import zipfile
|
||||
import pytest
|
||||
import aiohttp
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from unittest.mock import patch, MagicMock
|
||||
@ -117,13 +119,12 @@ async def write_file(path, z):
|
||||
f.write(chunk)
|
||||
|
||||
|
||||
async def test_import_project_containing_symlink(tmpdir, controller):
|
||||
|
||||
@pytest.fixture
|
||||
def export_project_with_symlink(tmpdir, controller):
|
||||
async def _export(symlink_target):
|
||||
project = Project(controller=controller, name="test")
|
||||
project.dump = MagicMock()
|
||||
path = project.path
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@ -134,12 +135,11 @@ async def test_import_project_containing_symlink(tmpdir, controller):
|
||||
"version": "2.0.0"
|
||||
}
|
||||
|
||||
with open(os.path.join(path, "project.gns3"), 'w+') as f:
|
||||
with open(os.path.join(project.path, "project.gns3"), 'w+') as f:
|
||||
json.dump(topology, f)
|
||||
|
||||
os.makedirs(os.path.join(path, "vm1", "dynamips"))
|
||||
os.makedirs(os.path.join(project.path, "vm1", "dynamips"))
|
||||
symlink_path = os.path.join(project.path, "vm1", "dynamips", "symlink")
|
||||
symlink_target = "/tmp/anywhere"
|
||||
os.symlink(symlink_target, symlink_path)
|
||||
|
||||
zip_path = str(tmpdir / "project.zip")
|
||||
@ -148,6 +148,20 @@ async def test_import_project_containing_symlink(tmpdir, controller):
|
||||
await export_project(z, project, str(tmpdir), include_images=False)
|
||||
await write_file(zip_path, z)
|
||||
|
||||
return zip_path
|
||||
|
||||
return _export
|
||||
|
||||
|
||||
async def test_import_project_containing_symlink(controller, export_project_with_symlink):
|
||||
"""
|
||||
Test importing a project containing a valid symlink (target inside the project directory).
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
symlink_target = "../symlink_target"
|
||||
zip_path = await export_project_with_symlink(symlink_target)
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
@ -158,6 +172,36 @@ async def test_import_project_containing_symlink(tmpdir, controller):
|
||||
assert os.readlink(symlink_path) == symlink_target
|
||||
|
||||
|
||||
async def test_import_project_containing_absolute_symlink(controller, export_project_with_symlink):
|
||||
"""
|
||||
Test importing a project containing an absolute symlink.
|
||||
This should fail because absolute symlinks are not allowed for security reasons.
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
symlink_target = "/tmp/anywhere"
|
||||
zip_path = await export_project_with_symlink(symlink_target)
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with open(zip_path, "rb") as f:
|
||||
await import_project(controller, project_id, f)
|
||||
|
||||
|
||||
async def test_import_project_containing_escaping_symlink(controller, export_project_with_symlink):
|
||||
"""
|
||||
Test importing a project containing a symlink that escapes the project directory.
|
||||
This should fail because symlinks that escape the project directory are not allowed for security reasons.
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
symlink_target = "../../../../symlink_target"
|
||||
zip_path = await export_project_with_symlink(symlink_target)
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with open(zip_path, "rb") as f:
|
||||
await import_project(controller, project_id, f)
|
||||
|
||||
|
||||
async def test_import_upgrade(tmpdir, controller):
|
||||
"""
|
||||
Topology made for previous GNS3 version are upgraded during the process
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user