Browse Source

Merge branch 'feature/iot-hub' into feature/lts-4.3-iot-hub

pull/15540/head
Igor Kulikov 4 months ago
parent
commit
d7aa0889ae
  1. 36
      application/src/main/java/org/thingsboard/server/service/solutions/DefaultSolutionService.java
  2. 3
      application/src/main/resources/thingsboard.yml

36
application/src/main/java/org/thingsboard/server/service/solutions/DefaultSolutionService.java

@ -144,6 +144,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
@ -181,6 +182,15 @@ public class DefaultSolutionService implements SolutionService {
@Value("${ui.solution_templates.docs_base_url:https://thingsboard.io/docs}") @Value("${ui.solution_templates.docs_base_url:https://thingsboard.io/docs}")
private String docsBaseUrl; private String docsBaseUrl;
@Value("${iot-hub.max-uncompressed-archive-bytes:209715200}")
private long maxUncompressedArchiveBytes;
@Value("${iot-hub.max-uncompressed-entry-bytes:52428800}")
private long maxUncompressedEntryBytes;
@Value("${iot-hub.max-archive-entry-count:10000}")
private int maxArchiveEntryCount;
private final RuleChainService ruleChainService; private final RuleChainService ruleChainService;
private final TbRuleChainService tbRuleChainService; private final TbRuleChainService tbRuleChainService;
private final DeviceProfileService deviceProfileService; private final DeviceProfileService deviceProfileService;
@ -1555,10 +1565,18 @@ public class DefaultSolutionService implements SolutionService {
return Collections.emptyList(); return Collections.emptyList();
} }
private static void extractZip(byte[] zipData, Path destDir) throws IOException { private static final int EXTRACT_BUFFER_SIZE = 8 * 1024;
private void extractZip(byte[] zipData, Path destDir) throws IOException {
long totalBytes = 0;
int entryCount = 0;
byte[] buf = new byte[EXTRACT_BUFFER_SIZE];
try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipData))) { try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipData))) {
ZipEntry entry; ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) { while ((entry = zis.getNextEntry()) != null) {
if (++entryCount > maxArchiveEntryCount) {
throw new IOException("Solution template archive exceeds max entry count: " + maxArchiveEntryCount);
}
Path entryPath = destDir.resolve(entry.getName()).normalize(); Path entryPath = destDir.resolve(entry.getName()).normalize();
if (!entryPath.startsWith(destDir)) { if (!entryPath.startsWith(destDir)) {
throw new IOException("ZIP entry outside of target directory: " + entry.getName()); throw new IOException("ZIP entry outside of target directory: " + entry.getName());
@ -1567,7 +1585,21 @@ public class DefaultSolutionService implements SolutionService {
Files.createDirectories(entryPath); Files.createDirectories(entryPath);
} else { } else {
Files.createDirectories(entryPath.getParent()); Files.createDirectories(entryPath.getParent());
Files.write(entryPath, zis.readAllBytes()); try (OutputStream out = Files.newOutputStream(entryPath)) {
long entryBytes = 0;
int n;
while ((n = zis.read(buf)) > 0) {
entryBytes += n;
totalBytes += n;
if (entryBytes > maxUncompressedEntryBytes) {
throw new IOException("Solution template entry exceeds max uncompressed size: " + entry.getName());
}
if (totalBytes > maxUncompressedArchiveBytes) {
throw new IOException("Solution template archive exceeds max uncompressed size: " + maxUncompressedArchiveBytes + " bytes");
}
out.write(buf, 0, n);
}
}
} }
zis.closeEntry(); zis.closeEntry();
} }

3
application/src/main/resources/thingsboard.yml

@ -2199,3 +2199,6 @@ iot-hub:
connect-timeout-sec: "${IOT_HUB_CONNECT_TIMEOUT_SEC:5}" # timeout in seconds to connect to IoT Hub server. connect-timeout-sec: "${IOT_HUB_CONNECT_TIMEOUT_SEC:5}" # timeout in seconds to connect to IoT Hub server.
read-timeout-sec: "${IOT_HUB_READ_TIMEOUT_SEC:10}" # timeout in seconds to read from IoT Hub server. read-timeout-sec: "${IOT_HUB_READ_TIMEOUT_SEC:10}" # timeout in seconds to read from IoT Hub server.
max-file-data-size-bytes: "${IOT_HUB_MAX_FILE_DATA_SIZE_BYTES:104857600}" # maximum size in bytes of a file-data payload fetched from IoT Hub. Requests advertising a larger Content-Length, or streams that exceed this size, are rejected to avoid out-of-memory issues on the platform side. max-file-data-size-bytes: "${IOT_HUB_MAX_FILE_DATA_SIZE_BYTES:104857600}" # maximum size in bytes of a file-data payload fetched from IoT Hub. Requests advertising a larger Content-Length, or streams that exceed this size, are rejected to avoid out-of-memory issues on the platform side.
max-uncompressed-archive-bytes: "${IOT_HUB_MAX_UNCOMPRESSED_ARCHIVE_BYTES:209715200}" # maximum cumulative uncompressed size in bytes for a solution template archive. Extraction aborts past this threshold to mitigate zip-bomb attacks.
max-uncompressed-entry-bytes: "${IOT_HUB_MAX_UNCOMPRESSED_ENTRY_BYTES:52428800}" # maximum uncompressed size in bytes for any single entry inside a solution template archive.
max-archive-entry-count: "${IOT_HUB_MAX_ARCHIVE_ENTRY_COUNT:10000}" # maximum number of entries allowed inside a solution template archive.

Loading…
Cancel
Save