From 5facf0db8d879e58183edbeeab969c09c7c2c4bd Mon Sep 17 00:00:00 2001 From: Charuka Tharindu Date: Thu, 7 Jul 2022 09:46:08 +0530 Subject: [PATCH 1/4] Add integrity checks before package installation --- .../ballerinalang/command/util/ToolUtil.java | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/ballerinalang/command/util/ToolUtil.java b/src/main/java/org/ballerinalang/command/util/ToolUtil.java index 90b22caf..970acec2 100644 --- a/src/main/java/org/ballerinalang/command/util/ToolUtil.java +++ b/src/main/java/org/ballerinalang/command/util/ToolUtil.java @@ -20,16 +20,7 @@ import me.tongfei.progressbar.ProgressBarStyle; import org.ballerinalang.command.Main; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.PrintWriter; +import java.io.*; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; @@ -37,6 +28,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -477,33 +470,61 @@ private static void downloadAndSetupDist(PrintStream printStream, HttpURLConnect String distPath = getDistributionsPath(); String zipFileLocation = getDistributionsPath() + File.separator + distribution + ".zip"; downloadFile(conn, zipFileLocation, distribution, printStream); - unzip(zipFileLocation, distPath); - addExecutablePermissionToFile(new File(distPath + File.separator + ToolUtil.getType(distribution) - + "-" + distribution + File.separator + "bin" - + File.separator + OSUtils.getExecutableFileName(distribution))); - - - String langServerPath = distPath + File.separator + distribution + File.separator + "lib" - + File.separator + "tools"; - File launcherServer = new File(langServerPath + File.separator + "lang-server" - + File.separator + "launcher" + File.separator + OSUtils.getLangServerLauncherName()); - File debugAdpater = new File(langServerPath + File.separator + "debug-adapter" - + File.separator + "launcher" + File.separator + OSUtils.getDebugAdapterName()); - - if (debugAdpater.exists()) { - addExecutablePermissionToFile(debugAdpater); - } + String downloadedDistSha = calcDistSHA(zipFileLocation); + String remoteDistSha = conn.getHeaderField("hash"); + if (downloadedDistSha.equals(remoteDistSha)) { + unzip(zipFileLocation, distPath); + addExecutablePermissionToFile(new File(distPath + File.separator + + ToolUtil.getType(distribution) + "-" + distribution + File.separator + "bin" + + File.separator + OSUtils.getExecutableFileName(distribution))); + + String langServerPath = distPath + File.separator + distribution + File.separator + "lib" + + File.separator + "tools"; + File launcherServer = new File(langServerPath + File.separator + "lang-server" + + File.separator + "launcher" + File.separator + OSUtils.getLangServerLauncherName()); + File debugAdpater = new File(langServerPath + File.separator + "debug-adapter" + + File.separator + "launcher" + File.separator + OSUtils.getDebugAdapterName()); + + if (debugAdpater.exists()) { + addExecutablePermissionToFile(debugAdpater); + } - if (launcherServer.exists()) { - addExecutablePermissionToFile(launcherServer); + if (launcherServer.exists()) { + addExecutablePermissionToFile(launcherServer); + } + } else { + printStream.println("Distribution is not activated due to integrity checks failure"); } - new File(zipFileLocation).delete(); + + } catch (NoSuchAlgorithmException e) { + throw ErrorUtil.createCommandException("unable to generate hashes for the distribution: " + e.getMessage()); + } catch (IOException e) { + throw ErrorUtil.createCommandException("Ballerina distribution not found: " + e.getMessage()); } finally { conn.disconnect(); } } + private static String calcDistSHA(String zipFileLocation) throws NoSuchAlgorithmException, IOException { + File zipFilePath = new File(zipFileLocation); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + InputStream inputStream = new FileInputStream(zipFilePath); + int n = 0; + byte[] buffer = new byte[8192]; + while (n != -1) { + n = inputStream.read(buffer); + if (n > 0) { + digest.update(buffer, 0, n); + } + } + StringBuilder result = new StringBuilder(); + for (byte b : digest.digest()) { + result.append(String.format("%02x", b)); + } + return result.toString(); + } + public static void getDependency(PrintStream printStream, String distribution, String distributionType, String distributionVersion) { HttpURLConnection conn = null; From 748efefc51bdddd2901c9fcf4d821c22ab7de040 Mon Sep 17 00:00:00 2001 From: Charuka Tharindu Date: Fri, 12 Aug 2022 16:26:00 +0530 Subject: [PATCH 2/4] Fix test failures --- gradle.properties | 7 +++ .../ballerinalang/command/util/ToolUtil.java | 49 ++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e7e1b506..208f173d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,10 +4,17 @@ ballerinaJreVersion=1.1.0 jreVersion=11.0.18+10 # For test purpose +<<<<<<< HEAD swan-lake-version=2201.2.0 swan-lake-spec-version=2022R3 swan-lake-latest-version=2201.5.0 swan-lake-latest-spec-version=2022R4 +======= +swan-lake-version=2201.0.0 +swan-lake-spec-version=2022R1 +swan-lake-latest-version=2201.1.1 +swan-lake-latest-spec-version=2022R2 +>>>>>>> 66f74a2 (Fix test failures) 1-x-channel-version=1.2.0 1-x-channel-spec-version=2020R1 1-x-channel-latest-version=1.2.38 diff --git a/src/main/java/org/ballerinalang/command/util/ToolUtil.java b/src/main/java/org/ballerinalang/command/util/ToolUtil.java index 970acec2..2631d51a 100644 --- a/src/main/java/org/ballerinalang/command/util/ToolUtil.java +++ b/src/main/java/org/ballerinalang/command/util/ToolUtil.java @@ -471,7 +471,7 @@ private static void downloadAndSetupDist(PrintStream printStream, HttpURLConnect String zipFileLocation = getDistributionsPath() + File.separator + distribution + ".zip"; downloadFile(conn, zipFileLocation, distribution, printStream); String downloadedDistSha = calcDistSHA(zipFileLocation); - String remoteDistSha = conn.getHeaderField("hash"); + String remoteDistSha = getDistSHA(distribution); if (downloadedDistSha.equals(remoteDistSha)) { unzip(zipFileLocation, distPath); addExecutablePermissionToFile(new File(distPath + File.separator @@ -506,6 +506,53 @@ private static void downloadAndSetupDist(PrintStream printStream, HttpURLConnect } } + private static String getDistSHA(String distribution) { + HttpURLConnection conn = null; + String hash = ""; + try { + URL url = new URL(getServerURL() + "/distributions"); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setRequestProperty("user-agent", + OSUtils.getUserAgent(getCurrentBallerinaVersion(), + getCurrentToolsVersion(), "jballerina")); + conn.setRequestProperty("Accept", "application/json"); + if (conn.getResponseCode() != 200) { + conn.disconnect(); + throw ErrorUtil.createCommandException(getServerRequestFailedErrorMessage(conn)); + } else { + String json = convertStreamToString(conn.getInputStream()); + Matcher matcher = Pattern.compile("\"version\":\"(.*?)\"").matcher(json); + int i = 0; + while (matcher.find()) { + if (!matcher.group(1).equals(distribution)) { + i++; + } else { + break; + } + } + + matcher = Pattern.compile("\"hash\":\"(.*?)\"").matcher(json); + int j = 0; + while (matcher.find()) { + if (j==i) { + hash = matcher.group(1); + break; + } else { + j++; + } + } + } + } catch (IOException e) { + throw ErrorUtil.createCommandException(CONNECTION_ERROR_MESSAGE); + } finally { + if (conn != null) { + conn.disconnect(); + } + } + return hash; + } + private static String calcDistSHA(String zipFileLocation) throws NoSuchAlgorithmException, IOException { File zipFilePath = new File(zipFileLocation); MessageDigest digest = MessageDigest.getInstance("SHA-1"); From 2e338b701c68104c96bf076550d9368b54deb63a Mon Sep 17 00:00:00 2001 From: Charuka Tharindu Date: Mon, 15 May 2023 17:15:58 +0530 Subject: [PATCH 3/4] Address review suggestions --- gradle.properties | 7 ---- .../ballerinalang/command/util/ToolUtil.java | 38 ++++++++++++------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/gradle.properties b/gradle.properties index 208f173d..e7e1b506 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,17 +4,10 @@ ballerinaJreVersion=1.1.0 jreVersion=11.0.18+10 # For test purpose -<<<<<<< HEAD swan-lake-version=2201.2.0 swan-lake-spec-version=2022R3 swan-lake-latest-version=2201.5.0 swan-lake-latest-spec-version=2022R4 -======= -swan-lake-version=2201.0.0 -swan-lake-spec-version=2022R1 -swan-lake-latest-version=2201.1.1 -swan-lake-latest-spec-version=2022R2 ->>>>>>> 66f74a2 (Fix test failures) 1-x-channel-version=1.2.0 1-x-channel-spec-version=2020R1 1-x-channel-latest-version=1.2.38 diff --git a/src/main/java/org/ballerinalang/command/util/ToolUtil.java b/src/main/java/org/ballerinalang/command/util/ToolUtil.java index 2631d51a..4a0c9771 100644 --- a/src/main/java/org/ballerinalang/command/util/ToolUtil.java +++ b/src/main/java/org/ballerinalang/command/util/ToolUtil.java @@ -20,7 +20,16 @@ import me.tongfei.progressbar.ProgressBarStyle; import org.ballerinalang.command.Main; -import java.io.*; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; @@ -470,9 +479,9 @@ private static void downloadAndSetupDist(PrintStream printStream, HttpURLConnect String distPath = getDistributionsPath(); String zipFileLocation = getDistributionsPath() + File.separator + distribution + ".zip"; downloadFile(conn, zipFileLocation, distribution, printStream); - String downloadedDistSha = calcDistSHA(zipFileLocation); - String remoteDistSha = getDistSHA(distribution); - if (downloadedDistSha.equals(remoteDistSha)) { + String downloadedDistHash = generateDistributionHash(zipFileLocation); + String remoteDistHash = getDistHash(distribution); + if (downloadedDistHash.equals(remoteDistHash)) { unzip(zipFileLocation, distPath); addExecutablePermissionToFile(new File(distPath + File.separator + ToolUtil.getType(distribution) + "-" + distribution + File.separator + "bin" @@ -506,7 +515,7 @@ private static void downloadAndSetupDist(PrintStream printStream, HttpURLConnect } } - private static String getDistSHA(String distribution) { + private static String getDistHash(String distribution) { HttpURLConnection conn = null; String hash = ""; try { @@ -553,16 +562,17 @@ private static String getDistSHA(String distribution) { return hash; } - private static String calcDistSHA(String zipFileLocation) throws NoSuchAlgorithmException, IOException { + private static String generateDistributionHash(String zipFileLocation) throws NoSuchAlgorithmException, IOException { File zipFilePath = new File(zipFileLocation); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - InputStream inputStream = new FileInputStream(zipFilePath); - int n = 0; - byte[] buffer = new byte[8192]; - while (n != -1) { - n = inputStream.read(buffer); - if (n > 0) { - digest.update(buffer, 0, n); + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + try (InputStream inputStream = new FileInputStream(zipFilePath)) { + int n = 0; + byte[] buffer = new byte[8192]; + while (n != -1) { + n = inputStream.read(buffer); + if (n > 0) { + digest.update(buffer, 0, n); + } } } StringBuilder result = new StringBuilder(); From 7b996ca71ec1f9c8e348a9973dd38315c5d16775 Mon Sep 17 00:00:00 2001 From: Charuka Tharindu Date: Thu, 1 Jun 2023 15:16:59 +0530 Subject: [PATCH 4/4] Update test cases --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index e7e1b506..1c816733 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,8 +6,8 @@ jreVersion=11.0.18+10 # For test purpose swan-lake-version=2201.2.0 swan-lake-spec-version=2022R3 -swan-lake-latest-version=2201.5.0 +swan-lake-latest-version=2201.6.0 swan-lake-latest-spec-version=2022R4 1-x-channel-version=1.2.0 1-x-channel-spec-version=2020R1 -1-x-channel-latest-version=1.2.38 +1-x-channel-latest-version=1.2.39