diff --git a/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java b/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java index 4e77ff661..bd404519a 100644 --- a/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java +++ b/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java @@ -75,9 +75,9 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository { @Override protected AbstractDbArtifact store(final String tenant, final DbArtifactHash base16Hashes, final String contentType, final String tempFile) throws IOException { - final File file = new File(tempFile); - return renameFileToSHA1Naming(tenant, file, + return renameFileToSHA1Naming( + tenant, file, new ArtifactFilesystem(file, base16Hashes.getSha1(), base16Hashes, file.length(), contentType)); } @@ -90,11 +90,16 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository { Files.move(file.toPath(), fileSHA1Naming.toPath()); } - return new ArtifactFilesystem(fileSHA1Naming, artifact.getArtifactId(), artifact.getHashes(), - artifact.getSize(), artifact.getContentType()); + return new ArtifactFilesystem( + fileSHA1Naming, artifact.getArtifactId(), artifact.getHashes(), artifact.getSize(), artifact.getContentType()); } private File getFile(final String tenant, final String sha1) { + // ensure that the sha1 is not a path traversal attack + if (sha1.indexOf('/') >= 0 || sha1.indexOf('\\') >= 0) { + throw new IllegalArgumentException("Invalid sha1 hash: " + sha1); + } + final File aritfactDirectory = getSha1DirectoryPath(tenant, sha1).toFile(); aritfactDirectory.mkdirs(); return new File(aritfactDirectory, sha1); diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index f40d28e5f..fc5c167ff 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -783,23 +783,14 @@ public class DdiRootController implements DdiRootControllerRestApi { * @throws IOException cannot write output stream */ private static ResponseEntity writeMD5FileResponse( - final HttpServletResponse response, final String md5Hash, - final String filename) throws IOException { + final HttpServletResponse response, final String md5Hash, final String filename) throws IOException { if (md5Hash == null) { return ResponseEntity.notFound().build(); } - final StringBuilder builder = new StringBuilder(); - builder.append(md5Hash); - builder.append(" "); - builder.append(filename); - final byte[] content = builder.toString().getBytes(StandardCharsets.US_ASCII); - - final StringBuilder header = new StringBuilder().append("attachment;filename=").append(filename) - .append(ARTIFACT_MD5_DWNL_SUFFIX); - + final byte[] content = (md5Hash + " " + filename).getBytes(StandardCharsets.US_ASCII); response.setContentLength(content.length); - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, header.toString()); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename + ARTIFACT_MD5_DWNL_SUFFIX); response.getOutputStream().write(content);