From 8cb2fec45dd90fda8ed9608c691f6bb8ed721cd2 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 6 Jun 2022 14:15:44 +0200 Subject: [PATCH] Restrict protocols available at project creation. Closes #4918. (#4919) --- .../refine/importing/ImportingUtilities.java | 7 +++ .../importing/ImportingUtilitiesTests.java | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/main/src/com/google/refine/importing/ImportingUtilities.java b/main/src/com/google/refine/importing/ImportingUtilities.java index 336ca25bfc13..a76f5b607983 100644 --- a/main/src/com/google/refine/importing/ImportingUtilities.java +++ b/main/src/com/google/refine/importing/ImportingUtilities.java @@ -48,6 +48,7 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT import java.nio.file.Path; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -96,6 +97,8 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT public class ImportingUtilities { final static protected Logger logger = LoggerFactory.getLogger("importing-utilities"); + final public static List allowedProtocols = Arrays.asList("http", "https", "ftp", "sftp"); + static public interface Progress { public void setProgress(String message, int percent); public boolean isCanceled(); @@ -262,6 +265,10 @@ public void update(long bytesRead, long contentLength, int itemCount) { String urlString = Streams.asString(stream); URL url = new URL(urlString); + if (!allowedProtocols.contains(url.getProtocol().toLowerCase())) { + throw new IOException("Unsupported protocol: " + url.getProtocol()); + } + ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode(); JSONUtilities.safePut(fileRecord, "origin", "download"); JSONUtilities.safePut(fileRecord, "url", urlString); diff --git a/main/tests/server/src/com/google/refine/importing/ImportingUtilitiesTests.java b/main/tests/server/src/com/google/refine/importing/ImportingUtilitiesTests.java index f32cdbd3ee34..bf1ad2004098 100644 --- a/main/tests/server/src/com/google/refine/importing/ImportingUtilitiesTests.java +++ b/main/tests/server/src/com/google/refine/importing/ImportingUtilitiesTests.java @@ -170,6 +170,55 @@ public boolean isCanceled() { } } + @Test + public void urlImportingInvalidProtocol() throws IOException { + + String url = "file:///etc/passwd"; + String message = "Unsupported protocol: file"; + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + StringBody stringBody = new StringBody(url.toString(), ContentType.MULTIPART_FORM_DATA); + builder = builder.addPart("download", stringBody); + HttpEntity entity = builder.build(); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + entity.writeTo(os); + ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); + + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getContentType()).thenReturn(entity.getContentType()); + when(req.getParameter("download")).thenReturn(url.toString()); + when(req.getMethod()).thenReturn("POST"); + when(req.getContentLength()).thenReturn((int) entity.getContentLength()); + when(req.getInputStream()).thenReturn(new MockServletInputStream(is)); + + ImportingJob job = ImportingManager.createJob(); + Properties parameters = ParsingUtilities.parseUrlParameters(req); + ObjectNode retrievalRecord = ParsingUtilities.mapper.createObjectNode(); + ObjectNode progress = ParsingUtilities.mapper.createObjectNode(); + try { + ImportingUtilities.retrieveContentFromPostRequest(req, parameters, job.getRawDataDir(), retrievalRecord, + new ImportingUtilities.Progress() { + + @Override + public void setProgress(String message, int percent) { + if (message != null) { + JSONUtilities.safePut(progress, "message", message); + } + JSONUtilities.safePut(progress, "percent", percent); + } + + @Override + public boolean isCanceled() { + return job.canceled; + } + }); + fail("No Exception was thrown"); + } catch (Exception exception) { + assertEquals(exception.getMessage(), message); + } + } + public static class MockServletInputStream extends ServletInputStream { private final InputStream delegate;