From b18a35191b7866b5145288717ea46ddef5c59bd5 Mon Sep 17 00:00:00 2001 From: Gayal Dassanayake Date: Thu, 9 May 2024 11:58:28 +0530 Subject: [PATCH 1/2] Add hash verification for tools --- .../org/ballerinalang/central/client/CentralAPIClient.java | 4 +++- .../ballerinalang/central/client/TestCentralApiClient.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java b/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java index 0b55427c1426..1b782bb36c56 100644 --- a/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java +++ b/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java @@ -689,6 +689,7 @@ public String[] pullTool(String toolId, String version, Path balaCacheDirPath, S Optional latestVersion = Optional.empty(); Optional balaUrl = Optional.empty(); Optional platform = Optional.empty(); + String digest = ""; if (body.isPresent()) { Optional contentType = Optional.ofNullable(body.get().contentType()); if (contentType.isPresent() && isApplicationJsonContentType(contentType.get().toString())) { @@ -699,6 +700,7 @@ public String[] pullTool(String toolId, String version, Path balaCacheDirPath, S balaUrl = Optional.ofNullable(jsonContent.get(BALA_URL).getAsString()); platform = Optional.of(jsonContent.get(PLATFORM).getAsString()) .or(() -> Optional.of(ANY_PLATFORM)); + digest = Optional.ofNullable(jsonContent.get(DIGEST).getAsString()).orElse(""); } } @@ -724,7 +726,7 @@ public String[] pullTool(String toolId, String version, Path balaCacheDirPath, S try { createBalaInHomeRepo(balaDownloadResponse, packagePathInBalaCache, org.get(), pkgName.get(), isNightlyBuild, null, balaUrl.get(), balaFileName, - enableOutputStream ? outStream : null, logFormatter, ""); + enableOutputStream ? outStream : null, logFormatter, digest); return new String[] { String.valueOf(true), org.get(), pkgName.get(), latestVersion.get() }; } catch (PackageAlreadyExistsException ignore) { // package already exists. setting org, name and version fields is enough diff --git a/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java b/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java index 48533f4ee53c..77e9fd6f5216 100644 --- a/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java +++ b/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java @@ -870,14 +870,14 @@ public void testPullTool() throws IOException, CentralClientException { " \"name\": \"toolbox\",\n" + " \"version\": \"0.1.0\",\n" + " \"balaURL\": \"" + toolBalaUrl + "\",\n" + - " \"platform\": \"java17\"\n}"); + " \"platform\": \"java17\",\n" + + " \"digest\": \"sha-256=623bae28884bbc9cd61eb684acf7921cf43cb1d19ed0e36766bf6a75b0cdb15b\"\n}"); Response mockResponse = new Response.Builder() .request(mockRequest) .protocol(Protocol.HTTP_1_1) .code(HttpURLConnection.HTTP_OK) .addHeader(LOCATION, this.balaUrl) .addHeader(CONTENT_DISPOSITION, balaFileName) - .addHeader(DIGEST, "sha-256=47e043c80d516234b1e6bd93140f126c9d9e79b5c7c0600cc6316d12504c2cf4") .message("") .body(mockResponseBody) .build(); From aff96d3ac31e89dc066c8e6276ec7498c9dee667 Mon Sep 17 00:00:00 2001 From: Gayal Dassanayake Date: Thu, 9 May 2024 12:01:37 +0530 Subject: [PATCH 2/2] Add a buffer for hash check --- .../main/java/org/ballerinalang/central/client/Utils.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cli/central-client/src/main/java/org/ballerinalang/central/client/Utils.java b/cli/central-client/src/main/java/org/ballerinalang/central/client/Utils.java index aab644c2ebcd..7b79b03c6aff 100644 --- a/cli/central-client/src/main/java/org/ballerinalang/central/client/Utils.java +++ b/cli/central-client/src/main/java/org/ballerinalang/central/client/Utils.java @@ -80,6 +80,7 @@ */ public class Utils { + private static final int BUFFER_SIZE = 1024; public static final String DEPRECATED_META_FILE_NAME = "deprecated.txt"; public static final boolean SET_BALLERINA_STAGE_CENTRAL = Boolean.parseBoolean( System.getenv(BALLERINA_STAGE_CENTRAL)); @@ -348,7 +349,7 @@ private static void writeAndHandleProgress(InputStream inputStream, FileOutputSt long totalSizeInKB, String fullPkgName, PrintStream outStream, LogFormatter logFormatter, Path homeRepo) throws IOException { int count; - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[BUFFER_SIZE]; String remoteRepo = getRemoteRepo(); String progressBarTask = fullPkgName + " [" + remoteRepo + " ->" + homeRepo + "] "; try (ProgressBar progressBar = new ProgressBar(progressBarTask, totalSizeInKB, 1000, @@ -365,7 +366,7 @@ private static void writeAndHandleProgress(InputStream inputStream, FileOutputSt private static void writeAndHandleProgressQuietly(InputStream inputStream, FileOutputStream outputStream) throws IOException { int count; - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[BUFFER_SIZE]; while ((count = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, count); @@ -479,7 +480,8 @@ public static String checkHash(String filePath, String algorithm) throws Central try (InputStream is = new FileInputStream(filePath); DigestInputStream dis = new DigestInputStream(is, md)) { - while (dis.read() != -1) { + byte[] buffer = new byte[BUFFER_SIZE]; + while (dis.read(buffer) != -1) { } md = dis.getMessageDigest(); return bytesToHex(md.digest());