You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2018/10/16 13:21:29 UTC

[cloudstack] branch 4.11 updated: Add checksum sanity validation on template registration (#2902)

This is an automated email from the ASF dual-hosted git repository.

rafael pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.11 by this push:
     new 9003c7b  Add checksum sanity validation on template registration (#2902)
9003c7b is described below

commit 9003c7bfdce9586aaeef19b1aea372b4fcfdb9b4
Author: Nicolas Vazquez <ni...@gmail.com>
AuthorDate: Tue Oct 16 10:21:20 2018 -0300

    Add checksum sanity validation on template registration (#2902)
    
    * Add checksum sanity validation on template registration
    
    * Refactor
    
    * Rename checksum sanity method
---
 .../cloud/template/HypervisorTemplateAdapter.java  |  3 +++
 .../cloudstack/utils/security/DigestHelper.java    | 27 +++++++++++++++++--
 .../utils/security/DigestHelperTest.java           | 30 ++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
index bfa73af..8aa2166 100644
--- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
@@ -39,6 +39,7 @@ import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplat
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
 import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand;
+import org.apache.cloudstack.utils.security.DigestHelper;
 import org.apache.log4j.Logger;
 import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
 import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
@@ -155,6 +156,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
         String url = profile.getUrl();
         UriUtils.validateUrl(ImageFormat.ISO.getFileExtension(), url);
         if (cmd.isDirectDownload()) {
+            DigestHelper.validateChecksumString(cmd.getChecksum());
             Long templateSize = performDirectDownloadUrlValidation(url);
             profile.setSize(templateSize);
         }
@@ -170,6 +172,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
         String url = profile.getUrl();
         UriUtils.validateUrl(cmd.getFormat(), url);
         if (cmd.isDirectDownload()) {
+            DigestHelper.validateChecksumString(cmd.getChecksum());
             Long templateSize = performDirectDownloadUrlValidation(url);
             profile.setSize(templateSize);
         }
diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java
index 67adf74..40b0c1c 100644
--- a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java
+++ b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java
@@ -16,6 +16,8 @@
 // under the License.
 package org.apache.cloudstack.utils.security;
 
+import org.apache.commons.lang.StringUtils;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
@@ -70,9 +72,9 @@ public class DigestHelper {
         return checksum;
     }
 
-    static final Map<String, Integer> paddingLengths = creatPaddingLengths();
+    static final Map<String, Integer> paddingLengths = getChecksumLengthsMap();
 
-    private static final Map<String, Integer> creatPaddingLengths() {
+    private static final Map<String, Integer> getChecksumLengthsMap() {
         Map<String, Integer> map = new HashMap<>();
         map.put("MD5", 32);
         map.put("SHA-1", 40);
@@ -93,4 +95,25 @@ public class DigestHelper {
         }
         return true;
     }
+
+    /**
+     * Checksum sanity for not empty checksum. Expected format: {ALG}HASH
+     * If ALG is missing, MD5 is assumed as default
+     * Hash length is verified, depending on the algorithm.
+     * IllegalArgumentException is thrown in case of malformed checksums
+     */
+    public static void validateChecksumString(String checksum) {
+        if(StringUtils.isNotEmpty(checksum)) {
+            ChecksumValue checksumValue = new ChecksumValue(checksum);
+            String digest = checksumValue.getChecksum();
+            Map<String, Integer> map = getChecksumLengthsMap();
+            if (!map.containsKey(checksumValue.getAlgorithm())) {
+                throw new IllegalArgumentException("Algorithm " + checksumValue.getAlgorithm() + " was provided but it is not one of the supported algorithms");
+            }
+            Integer expectedLength = map.get(checksumValue.getAlgorithm());
+            if (digest.length() != expectedLength) {
+                throw new IllegalArgumentException("Checksum digest length should be " + expectedLength + " instead of " + digest.length());
+            }
+        }
+    }
 }
diff --git a/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java b/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java
index 4540882..4a6e3f7 100644
--- a/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java
+++ b/utils/src/test/java/org/apache/cloudstack/utils/security/DigestHelperTest.java
@@ -32,8 +32,10 @@ public class DigestHelperTest {
     private final static String INPUT_STRING_NO2 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789b\n";
     private final static String INPUT_STRING_NO3 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789h\n";
     private final static String SHA256_CHECKSUM = "{SHA-256}c6ab15af7842d23d3c06c138b53a7d09c5e351a79c4eb3c8ca8d65e5ce8900ab";
+    private final static String SHA256_NO_PREFIX_CHECKSUM = "c6ab15af7842d23d3c06c138b53a7d09c5e351a79c4eb3c8ca8d65e5ce8900ab";
     private final static String SHA1_CHECKSUM = "{SHA-1}49e4b2f4292b63e88597c127d11bc2cc0f2ca0ff";
     private final static String MD5_CHECKSUM = "{MD5}d141a8eeaf6bba779d1d1dc5102a81c5";
+    private final static String MD5_NO_PREFIX_CHECKSUM = "d141a8eeaf6bba779d1d1dc5102a81c5";
     private final static String ZERO_PADDED_MD5_CHECKSUM = "{MD5}0e51dfa74b87f19dd5e0124d6a2195e3";
     private final static String ZERO_PADDED_SHA256_CHECKSUM = "{SHA-256}08b5ae0c7d7d45d8ed406d7c3c7da695b81187903694314d97f8a37752a6b241";
     private static final String MD5 = "MD5";
@@ -97,6 +99,34 @@ public class DigestHelperTest {
     public void reset() throws IOException {
         inputStream.reset();
     }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testChecksumSanityNoPrefixWrongAlgorithm() {
+        DigestHelper.validateChecksumString(SHA256_NO_PREFIX_CHECKSUM);
+    }
+
+    @Test
+    public void testChecksumSanityNoPrefix() {
+        DigestHelper.validateChecksumString(MD5_NO_PREFIX_CHECKSUM);
+    }
+
+    @Test
+    public void testChecksumSanityPrefixEmptyAlgorithm() {
+        String checksum = "{}" + MD5_NO_PREFIX_CHECKSUM;
+        DigestHelper.validateChecksumString(checksum);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testChecksumSanityPrefixWrongAlgorithm() {
+        String checksum = "{MD5}" + SHA256_NO_PREFIX_CHECKSUM;
+        DigestHelper.validateChecksumString(checksum);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testChecksumSanityPrefixWrongChecksumLength() {
+        String checksum = SHA256_CHECKSUM + "XXXXX";
+        DigestHelper.validateChecksumString(checksum);
+    }
 }
 
 //Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme
\ No newline at end of file