Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Jenkinsfile.talend
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ org.apache.camel:camel-as2-api,\
org.apache.camel:camel-aws2-kinesis,\
org.apache.camel:camel-aws2-s3,\
org.apache.camel:camel-aws2-sqs,\
org.apache.camel:camel-azure-storage-blob,\
org.apache.camel:camel-azure-storage-datalake,\
org.apache.camel:camel-coap,\
org.apache.camel:camel-cometd,\
org.apache.camel:camel-consul,\
org.apache.camel:camel-crypto,\
org.apache.camel:camel-cxf-common,\
Expand Down Expand Up @@ -79,6 +82,7 @@ org.apache.camel:camel-salesforce,\
org.apache.camel:camel-sjms,\
org.apache.camel:camel-sjms2,\
org.apache.camel:camel-smb,\
org.apache.camel:camel-solr,\
org.apache.camel:camel-spring,\
org.apache.camel:camel-sql,\
org.apache.camel:camel-tika,\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"exceptionHandler": { "index": 15, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 16, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"disconnectLocalSession": { "index": 17, "kind": "parameter", "displayName": "Disconnect Local Session", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disconnect local sessions after publishing a message to its channel. Disconnecting local session is needed as they are not swept by default by CometD, and therefore you can run out of memory." },
"lazyStartProducer": { "index": 18, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
"lazyStartProducer": { "index": 18, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"headerFilterStrategy": { "index": 19, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers." }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"exceptionHandler": { "index": 15, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 16, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"disconnectLocalSession": { "index": 17, "kind": "parameter", "displayName": "Disconnect Local Session", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disconnect local sessions after publishing a message to its channel. Disconnecting local session is needed as they are not swept by default by CometD, and therefore you can run out of memory." },
"lazyStartProducer": { "index": 18, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
"lazyStartProducer": { "index": 18, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"headerFilterStrategy": { "index": 19, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers." }
}
}
2 changes: 2 additions & 0 deletions components/camel-azure/camel-azure-storage-blob/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@

<name>Camel :: Azure :: Storage Blob</name>
<description>Camel Azure Blob Storage Service Component</description>
<version>${revision}</version>

<properties>
<revision>${camel-azure-storage-blob.tesb.version}</revision>
<!-- Azurite is not available on these platforms -->
<skipITs.ppc64le>true</skipITs.ppc64le>
<skipITs.s390x>true</skipITs.s390x>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.Collections;
Expand Down Expand Up @@ -129,7 +130,7 @@ public BlobOperationResponse downloadBlobToFile(final Exchange exchange) {
throw new IllegalArgumentException("In order to download a blob, you will need to specify the fileDir in the URI");
}

final File fileToDownload = new File(fileDir, client.getBlobName());
final File fileToDownload = resolveWithinDirectory(fileDir, client.getBlobName());
final BlobCommonRequestOptions commonRequestOptions = getCommonRequestOptions(exchange);
final BlobRange blobRange = configurationProxy.getBlobRange(exchange);
final ParallelTransferOptions parallelTransferOptions = configurationProxy.getParallelTransferOptions(exchange);
Expand Down Expand Up @@ -484,4 +485,18 @@ private void closeInputStreamIfNeeded(InputStream inputStream) throws IOExceptio
inputStream.close();
}
}

private static File resolveWithinDirectory(String fileDir, String name) {
final File target = new File(fileDir, name);
// normalize lexically (removes ./ and ../ segments) and compare on path-segment boundaries so a sibling
// directory whose name merely extends fileDir is not considered contained
final Path normalizedDir = new File(fileDir).toPath().normalize();
final Path normalizedTarget = target.toPath().normalize();
if (!normalizedTarget.startsWith(normalizedDir)) {
throw new IllegalArgumentException(
"Cannot download to file '" + name
+ "' as it resolves outside the configured fileDir directory: " + fileDir);
}
return target;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ void testGetBlob() throws IOException {
assertEquals("tag1", response3.getHeaders().get(BlobConstants.E_TAG));
}

@Test
void testDownloadBlobToFileRejectsPathTraversalName() {
// a blob name is influenced by whoever writes to the container and may contain ../ segments;
// the download must stay within the configured fileDir
configuration.setFileDir("/tmp/camel-azure-blob-download");
when(client.getBlobName()).thenReturn("../escaped/PROOF_PWNED");

final BlobOperations operations = new BlobOperations(configuration, client);
final Exchange exchange = new DefaultExchange(context);

assertThrows(IllegalArgumentException.class, () -> operations.downloadBlobToFile(exchange));
}

@Test
void testUploadBlockBlob() throws Exception {
// mocking
Expand Down
5 changes: 5 additions & 0 deletions components/camel-azure/camel-azure-storage-datalake/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@

<name>Camel :: Azure :: Storage Datalake</name>
<description>Camel Azure Datalake Component</description>
<version>${revision}</version>

<properties>
<revision>${camel-azure-storage-datalake.tesb.version}</revision>
</properties>

<dependencies>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.Map;
Expand Down Expand Up @@ -106,7 +107,7 @@ public DataLakeOperationResponse downloadToFile(final Exchange exchange) {
throw new IllegalArgumentException("to download a file, you need to specify the fileDir in the URI");
}
final DataLakeFileClientWrapper fileClientWrapper = getFileClientWrapper(exchange);
final File recieverFile = new File(fileDir, fileClientWrapper.getFileName());
final File recieverFile = resolveWithinDirectory(fileDir, fileClientWrapper.getFileName());
final FileCommonRequestOptions commonRequestOptions = getCommonRequestOptions(exchange);
final FileRange fileRange = configurationProxy.getFileRange(exchange);
final ParallelTransferOptions parallelTransferOptions = configurationProxy.getParallelTransferOptions(exchange);
Expand Down Expand Up @@ -253,4 +254,18 @@ private DataLakeFileClientWrapper getFileClientWrapper(final Exchange exchange)
final DataLakeFileClient fileClient = configurationProxy.getFileClient(exchange);
return null == fileClient ? client : new DataLakeFileClientWrapper(fileClient);
}

private static File resolveWithinDirectory(String fileDir, String name) {
final File target = new File(fileDir, name);
// normalize lexically (removes ./ and ../ segments) and compare on path-segment boundaries so a sibling
// directory whose name merely extends fileDir is not considered contained
final Path normalizedDir = new File(fileDir).toPath().normalize();
final Path normalizedTarget = target.toPath().normalize();
if (!normalizedTarget.startsWith(normalizedDir)) {
throw new IllegalArgumentException(
"Cannot download to file '" + name
+ "' as it resolves outside the configured fileDir directory: " + fileDir);
}
return target;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
Expand Down Expand Up @@ -93,6 +94,19 @@ void testGetFile() throws IOException {
assertNotNull(secondResponse.getHeaders());
}

@Test
void testDownloadToFileRejectsPathTraversalName() {
// a file name is influenced by whoever writes to the file system and may contain ../ segments;
// the download must stay within the configured fileDir
configuration.setFileDir("/tmp/camel-azure-datalake-download");
when(client.getFileName()).thenReturn("../escaped/PROOF_PWNED");

final DataLakeFileOperations operations = new DataLakeFileOperations(configuration, client);
final Exchange exchange = new DefaultExchange(context);

assertThrows(IllegalArgumentException.class, () -> operations.downloadToFile(exchange));
}

@Test
void testUploadFile() throws Exception {
final OffsetDateTime time = OffsetDateTime.now();
Expand Down
2 changes: 2 additions & 0 deletions components/camel-cometd/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
<packaging>jar</packaging>
<name>Camel :: Cometd</name>
<description>Camel Cometd support based on Jetty</description>
<version>${revision}</version>

<properties>
<revision>${camel-cometd.tesb.version}</revision>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true;
case "filterpath":
case "filterPath": target.setFilterPath(property(camelContext, java.lang.String.class, value)); return true;
case "headerfilterstrategy":
case "headerFilterStrategy": target.setHeaderFilterStrategy(property(camelContext, org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true;
case "interval": target.setInterval(property(camelContext, int.class, value)); return true;
case "jsoncommented":
case "jsonCommented": target.setJsonCommented(property(camelContext, boolean.class, value)); return true;
Expand Down Expand Up @@ -76,6 +78,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "exchangePattern": return org.apache.camel.ExchangePattern.class;
case "filterpath":
case "filterPath": return java.lang.String.class;
case "headerfilterstrategy":
case "headerFilterStrategy": return org.apache.camel.spi.HeaderFilterStrategy.class;
case "interval": return int.class;
case "jsoncommented":
case "jsonCommented": return boolean.class;
Expand Down Expand Up @@ -114,6 +118,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "exchangePattern": return target.getExchangePattern();
case "filterpath":
case "filterPath": return target.getFilterPath();
case "headerfilterstrategy":
case "headerFilterStrategy": return target.getHeaderFilterStrategy();
case "interval": return target.getInterval();
case "jsoncommented":
case "jsonCommented": return target.isJsonCommented();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CometdEndpointUriFactory extends org.apache.camel.support.component
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
Set<String> props = new HashSet<>(19);
Set<String> props = new HashSet<>(20);
props.add("allowedOrigins");
props.add("baseResource");
props.add("bridgeErrorHandler");
Expand All @@ -34,6 +34,7 @@ public class CometdEndpointUriFactory extends org.apache.camel.support.component
props.add("exceptionHandler");
props.add("exchangePattern");
props.add("filterPath");
props.add("headerFilterStrategy");
props.add("host");
props.add("interval");
props.add("jsonCommented");
Expand Down
Loading
Loading