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 <nicovazque...@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