Skip to content

Commit

Permalink
update a sonar issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Thorsten Marx committed Sep 17, 2024
1 parent dc66702 commit 92c6a2e
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 237 deletions.
4 changes: 4 additions & 0 deletions cms-extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/



import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
Expand All @@ -40,6 +37,10 @@
*/
public class InstallationHelper {

private final static int THRESHOLD_ENTRIES = 1000;
private final static int THRESHOLD_SIZE = 100_000_000;
private final static double THRESHOLD_RATIO = 10;

/**
* Delets a dir recursively deleting anything inside it.
*
Expand All @@ -62,8 +63,8 @@ public static boolean deleteDirectory(File dir) {
}
return dir.delete();
}
public static boolean moveDirectoy (final File src, final File dest) {

public static boolean moveDirectoy(final File src, final File dest) {
return src.renameTo(dest);
}

Expand All @@ -84,8 +85,15 @@ public static File unpackArchive(File theFile, File targetDir) throws IOExceptio
}
boolean found = false;
String moduleid = null;

int totalSizeArchive = 0;
int totalEntryArchive = 0;

try (ZipFile zipFile = new ZipFile(theFile)) {
for (Enumeration entries = zipFile.entries(); entries.hasMoreElements();) {

totalEntryArchive++;

ZipEntry entry = (ZipEntry) entries.nextElement();
File file = new File(targetDir, File.separator + entry.getName());
if (entry.isDirectory() && !found) {
Expand All @@ -96,24 +104,41 @@ public static File unpackArchive(File theFile, File targetDir) throws IOExceptio
throw new IOException("Could not create directory: " + file.getParentFile());
}
if (!entry.isDirectory()) {
copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(file)));
int totalSizeEntry = copyInputStream(entry, zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(file)));
totalSizeArchive += totalSizeEntry;
} else if (!buildDirectory(file)) {
throw new IOException("Could not create directory: " + file);
}
if (totalSizeArchive > THRESHOLD_SIZE) {
// the uncompressed data size is too much for the application resource capacity
throw new InstallationSecurityException("max size (%d bytes) reached".formatted(THRESHOLD_SIZE));
}

if (totalEntryArchive > THRESHOLD_ENTRIES) {
// too much entries in this archive, can lead to inodes exhaustion of the system
throw new InstallationSecurityException("max entries (%d) reached".formatted(THRESHOLD_ENTRIES));
}
}
}
return new File(targetDir, moduleid);
}

private static void copyInputStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len >= 0) {
out.write(buffer, 0, len);
len = in.read(buffer);
private static int copyInputStream(ZipEntry ze, InputStream in, OutputStream out) throws IOException {
int totalSizeEntry = 0;
try (in; out) {
byte[] buffer = new byte[1024];
int len = -1;
while ((len = in.read(buffer)) > 0) {
totalSizeEntry += len;
out.write(buffer, 0, len);

double compressionRatio = totalSizeEntry / ze.getCompressedSize();
if (compressionRatio > THRESHOLD_RATIO) {
throw new InstallationSecurityException("compression ratio () to high, maybe zip bomb detected".formatted(THRESHOLD_RATIO));
}
}
}
in.close();
out.close();
return totalSizeEntry;
}

private static boolean buildDirectory(File file) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.condation.cms.extensions.repository;

/*-
* #%L
* cms-extensions
* %%
* Copyright (C) 2023 - 2024 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/

/**
*
* @author t.marx
*/
public class InstallationSecurityException extends RuntimeException {

/**
* Creates a new instance of <code>InstallationSecurityException</code> without detail message.
*/
public InstallationSecurityException() {
}

/**
* Constructs an instance of <code>InstallationSecurityException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public InstallationSecurityException(String msg) {
super(msg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/


import java.io.File;
import java.io.IOException;
import java.net.URI;
Expand All @@ -31,9 +29,11 @@
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.SystemUtils;
import org.yaml.snakeyaml.Yaml;

/**
Expand Down Expand Up @@ -94,14 +94,22 @@ public void download(String url, Path target) {

try {
Path tempDirectory = Files.createTempDirectory("modules");
if (SystemUtils.IS_OS_UNIX) {
Files.setPosixFilePermissions(tempDirectory, PosixFilePermissions.fromString("rwx------"));
} else {
var f = tempDirectory.toFile();
f.setReadable(true, true);
f.setWritable(true, true);
f.setExecutable(true, true);
}

var request = HttpRequest.newBuilder(URI.create(url)).GET().build();
HttpResponse<Path> response = client.send(
request,
request,
HttpResponse.BodyHandlers.ofFile(tempDirectory.resolve(System.currentTimeMillis() + ".zip")));

var downloaded = response.body();

File moduleTempDir = InstallationHelper.unpackArchive(downloaded.toFile(), tempDirectory.toFile());

InstallationHelper.moveDirectoy(moduleTempDir, target.resolve(moduleTempDir.getName()).toFile());
Expand Down
10 changes: 0 additions & 10 deletions cms-server/src/test/java/com/condation/cms/MockModuleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,6 @@ public <T extends ExtensionPoint> List<T> extensions(Class<T> type) {
return Collections.emptyList();
}

@Override
public String installModule(URI uri) throws IOException {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}

@Override
public boolean uninstallModule(String string, boolean bln) throws IOException {
return true;
}

@Override
public Module module(String string) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@



import com.condation.modules.api.Module;
import java.io.IOException;
import java.net.URI;
import java.util.List;

/**
Expand Down Expand Up @@ -71,25 +69,6 @@ public interface ModuleManager extends AutoCloseable {
*/
<T extends ExtensionPoint> List<T> extensions(Class<T> extensionClass);

/**
* install a new module.
*
* @param moduleURI
* @return the id of the newly installed module.
* @throws IOException
*/
String installModule(final URI moduleURI) throws IOException;

/**
* uninstall module,
*
* @param moduleId the ID of the module
* @param deleteData should the data directory of the module be deleted too.
* @return
* @throws IOException
*/
boolean uninstallModule(final String moduleId, final boolean deleteData) throws IOException;

public Module module(final String id);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
import com.condation.modules.api.ModuleRequestContextFactory;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -363,69 +360,6 @@ public boolean deactivateModule(final String moduleId) throws IOException {

}

/**
* install a new module.
*
* @param moduleURI
* @return the id of the newly installed module.
* @throws IOException
*/
@Override
public String installModule(final URI moduleURI) throws IOException {

Path tempDirectory = Files.createTempDirectory("modules");
File moduleTempDir = ModulePacker.unpackArchive(new File(moduleURI), tempDirectory.toFile());
File moduleData = modulesDataPath;
ModuleImpl tempModule = new ModuleImpl(moduleTempDir, moduleData, this.context,
this.injector, this.requestContextFactory);
if (getModuleIds().contains(tempModule.getId())) {
deactivateModule(tempModule.getId());
uninstallModule(tempModule.getId(), false);
}
ModulePacker.moveDirectoy(moduleTempDir, new File(this.modulesPath, moduleTempDir.getName()));
File moduleDir = new File(this.modulesPath, moduleTempDir.getName());

ModuleImpl module = new ModuleImpl(moduleDir, moduleData, this.context,
this.injector, this.requestContextFactory);

ManagerConfiguration.ModuleConfig config = configuration.get(module.getId());
if (config == null) {
config = new ManagerConfiguration.ModuleConfig(module.getId()).setModuleDir(moduleDir.getName());
}
config.setActive(false);
configuration.add(config);

return module.getId();
}

/**
* uninstall module,
*
* @param moduleId the ID of the module
* @param deleteData should the data directory of the module be deleted too.
* @return
* @throws IOException
*/
@Override
public boolean uninstallModule(final String moduleId, final boolean deleteData) throws IOException {
if (configuration.get(moduleId) != null && configuration.get(moduleId).isActive()) {
throw new IOException("module must be deactivated first");
} else if (configuration.get(moduleId) == null) {
return true;
}

configuration.remove(moduleId);

boolean deleted = ModulePacker.deleteDirectory(new File(modulesPath, moduleId));

File moduleData = new File(modulesDataPath, moduleId);
if (deleteData && deleted && moduleData.exists()) {
deleted = ModulePacker.deleteDirectory(moduleData);
}

return deleted;
}

/**
* Returns all Extensions of the given type.
*
Expand Down
Loading

0 comments on commit 92c6a2e

Please sign in to comment.