You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/12/23 11:57:13 UTC

[camel] branch camel-3.20.x updated (6236cf1eaf8 -> 94afc38371d)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a change to branch camel-3.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git


    from 6236cf1eaf8 Publish documentation for Camel 3.20.x
     new fb8eb8d9a1e [CAMEL-15111] Fixes bug in camel-as2 via not forcing ascii charset when not specified (#8944)
     new 94afc38371d CAMEL-15111: Move as2-lib to parent

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 camel-dependencies/pom.xml                         |  1 +
 components/camel-as2/camel-as2-api/pom.xml         |  7 ++
 .../component/as2/api/entity/EntityParser.java     | 87 +++++++++++-----------
 .../as2/api/io/AS2SessionInputBuffer.java          |  9 +++
 .../camel/component/as2/api/AS2MessageTest.java    | 77 +++++++++++++++++++
 parent/pom.xml                                     |  1 +
 6 files changed, 139 insertions(+), 43 deletions(-)


[camel] 01/02: [CAMEL-15111] Fixes bug in camel-as2 via not forcing ascii charset when not specified (#8944)

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-3.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit fb8eb8d9a1e8711ba2f0f78557ad95db6d763567
Author: Yasser Zamani <ya...@apache.org>
AuthorDate: Fri Dec 23 14:53:00 2022 +0330

    [CAMEL-15111] Fixes bug in camel-as2 via not forcing ascii charset when not specified (#8944)
    
    * add CAMEL-15111 reproducer test case
    
    * fix CAMEL-15111 via not forcing ascii charset when not specified
    
    otherwise you will get java.nio.charset.MalformedInputException: Input length = 1 when content transfer encoding is binary
    
    * fix maven checkstyle errors
    
    * maven formatter:format
    
    * do not use a static version inside the component pom
    
    this should be in a property placeholder in parent pom
---
 components/camel-as2/camel-as2-api/pom.xml         |  7 ++
 .../component/as2/api/entity/EntityParser.java     | 87 +++++++++++-----------
 .../as2/api/io/AS2SessionInputBuffer.java          |  9 +++
 .../camel/component/as2/api/AS2MessageTest.java    | 77 +++++++++++++++++++
 components/camel-as2/pom.xml                       |  4 +
 5 files changed, 141 insertions(+), 43 deletions(-)

diff --git a/components/camel-as2/camel-as2-api/pom.xml b/components/camel-as2/camel-as2-api/pom.xml
index 712fd8c6c09..28e2c325029 100644
--- a/components/camel-as2/camel-as2-api/pom.xml
+++ b/components/camel-as2/camel-as2-api/pom.xml
@@ -96,6 +96,13 @@
             <artifactId>camel-test-junit5</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- added for binary content transfer encoding test because Camel AS2 client doesn't support binary currently -->
+        <dependency>
+            <groupId>com.helger.as2</groupId>
+            <artifactId>as2-lib</artifactId>
+            <version>${as2-lib-version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
index 85bede10230..01b4c7398cc 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
@@ -29,6 +29,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 
+import org.apache.camel.CamelException;
 import org.apache.camel.component.as2.api.AS2Header;
 import org.apache.camel.component.as2.api.AS2MimeType;
 import org.apache.camel.component.as2.api.io.AS2SessionInputBuffer;
@@ -37,6 +38,7 @@ import org.apache.camel.component.as2.api.util.ContentTypeUtils;
 import org.apache.camel.component.as2.api.util.DispositionNotificationContentUtils;
 import org.apache.camel.component.as2.api.util.EntityUtils;
 import org.apache.camel.component.as2.api.util.HttpMessageUtils;
+import org.apache.commons.codec.DecoderException;
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpException;
@@ -50,6 +52,7 @@ import org.apache.http.message.BasicLineParser;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.message.LineParser;
 import org.apache.http.message.ParserCursor;
+import org.apache.http.protocol.HTTP;
 import org.apache.http.util.Args;
 import org.apache.http.util.CharArrayBuffer;
 import org.bouncycastle.cms.CMSCompressedData;
@@ -907,22 +910,14 @@ public final class EntityParser {
         CharsetDecoder previousDecoder = inbuffer.getCharsetDecoder();
 
         try {
+            byte[] signature = parseBodyPartBytes(inbuffer, boundary, contentType, contentTransferEncoding);
+
             Charset charset = contentType.getCharset();
             if (charset == null) {
                 charset = StandardCharsets.US_ASCII;
             }
-            CharsetDecoder charsetDecoder = charset.newDecoder();
-
-            inbuffer.setCharsetDecoder(charsetDecoder);
-
-            String pkcs7SignatureBodyContent = parseBodyPartText(inbuffer, boundary);
-
-            byte[] signature = EntityUtils.decode(pkcs7SignatureBodyContent.getBytes(charset), contentTransferEncoding);
-
             String charsetName = charset.toString();
-            ApplicationPkcs7SignatureEntity applicationPkcs7SignatureEntity = new ApplicationPkcs7SignatureEntity(
-                    signature, charsetName, contentTransferEncoding, false);
-            return applicationPkcs7SignatureEntity;
+            return new ApplicationPkcs7SignatureEntity(signature, charsetName, contentTransferEncoding, false);
         } catch (Exception e) {
             ParseException parseException = new ParseException("failed to parse PKCS7 Signature entity");
             parseException.initCause(e);
@@ -942,21 +937,8 @@ public final class EntityParser {
         CharsetDecoder previousDecoder = inbuffer.getCharsetDecoder();
 
         try {
-            Charset charset = contentType.getCharset();
-            if (charset == null) {
-                charset = StandardCharsets.US_ASCII;
-            }
-            CharsetDecoder charsetDecoder = charset.newDecoder();
-
-            inbuffer.setCharsetDecoder(charsetDecoder);
-
-            String pkcs7EncryptedBodyContent = parseBodyPartText(inbuffer, boundary);
-
-            byte[] encryptedContent = EntityUtils.decode(pkcs7EncryptedBodyContent.getBytes(charset), contentTransferEncoding);
-
-            ApplicationPkcs7MimeEnvelopedDataEntity applicationPkcs7MimeEntity = new ApplicationPkcs7MimeEnvelopedDataEntity(
-                    encryptedContent, contentTransferEncoding, false);
-            return applicationPkcs7MimeEntity;
+            byte[] encryptedContent = parseBodyPartBytes(inbuffer, boundary, contentType, contentTransferEncoding);
+            return new ApplicationPkcs7MimeEnvelopedDataEntity(encryptedContent, contentTransferEncoding, false);
         } catch (Exception e) {
             ParseException parseException = new ParseException("failed to parse PKCS7 Mime entity");
             parseException.initCause(e);
@@ -976,22 +958,8 @@ public final class EntityParser {
         CharsetDecoder previousDecoder = inbuffer.getCharsetDecoder();
 
         try {
-            Charset charset = contentType.getCharset();
-            if (charset == null) {
-                charset = StandardCharsets.US_ASCII;
-            }
-            CharsetDecoder charsetDecoder = charset.newDecoder();
-
-            inbuffer.setCharsetDecoder(charsetDecoder);
-
-            String pkcs7CompressedBodyContent = parseBodyPartText(inbuffer, boundary);
-
-            byte[] compressedContent = EntityUtils.decode(pkcs7CompressedBodyContent.getBytes(charset),
-                    contentTransferEncoding);
-
-            ApplicationPkcs7MimeCompressedDataEntity applicationPkcs7MimeEntity = new ApplicationPkcs7MimeCompressedDataEntity(
-                    compressedContent, contentTransferEncoding, false);
-            return applicationPkcs7MimeEntity;
+            byte[] compressedContent = parseBodyPartBytes(inbuffer, boundary, contentType, contentTransferEncoding);
+            return new ApplicationPkcs7MimeCompressedDataEntity(compressedContent, contentTransferEncoding, false);
         } catch (Exception e) {
             ParseException parseException = new ParseException("failed to parse PKCS7 Mime entity");
             parseException.initCause(e);
@@ -1001,6 +969,36 @@ public final class EntityParser {
         }
     }
 
+    public static byte[] parseBodyPartBytes(
+            final AS2SessionInputBuffer inbuffer,
+            final String boundary,
+            ContentType contentType,
+            String contentTransferEncoding)
+            throws IOException, CamelException, DecoderException {
+
+        Charset charset = contentType.getCharset();
+        if (charset != null) {
+            CharsetDecoder charsetDecoder = charset.newDecoder();
+            inbuffer.setCharsetDecoder(charsetDecoder);
+        } else {
+            inbuffer.setCharsetDecoder(null);
+        }
+
+        String bodyContent = parseBodyPartText(inbuffer, boundary);
+
+        byte[] bodyContentBytes;
+        if (charset != null) {
+            bodyContentBytes = bodyContent.getBytes(charset);
+        } else {
+            bodyContentBytes = new byte[bodyContent.length()];
+            for (int i = 0; i < bodyContent.length(); i++) {
+                bodyContentBytes[i] = (byte) bodyContent.charAt(i);
+            }
+        }
+
+        return EntityUtils.decode(bodyContentBytes, contentTransferEncoding);
+    }
+
     public static String parseBodyPartText(
             final AS2SessionInputBuffer inbuffer,
             final String boundary)
@@ -1021,8 +1019,11 @@ public final class EntityParser {
             }
 
             buffer.append(line);
+            if (inbuffer.isLastLineReadEnrichedByCarriageReturn()) {
+                buffer.append((char) HTTP.CR);
+            }
             if (inbuffer.isLastLineReadTerminatedByLineFeed()) {
-                buffer.append("\r\n");
+                buffer.append((char) HTTP.LF);
             }
             line.clear();
         }
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2SessionInputBuffer.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2SessionInputBuffer.java
index d4fad28fdf5..2936cf0b158 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2SessionInputBuffer.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2SessionInputBuffer.java
@@ -52,6 +52,7 @@ public class AS2SessionInputBuffer implements SessionInputBuffer, BufferInfo {
     private int bufferlen;
     private CharBuffer cbuf;
 
+    private boolean lastLineReadEnrichedByCarriageReturn;
     private boolean lastLineReadTerminatedByLineFeed;
 
     public AS2SessionInputBuffer(final HttpTransportMetricsImpl metrics,
@@ -190,6 +191,7 @@ public class AS2SessionInputBuffer implements SessionInputBuffer, BufferInfo {
         final int maxLineLen = this.constraints.getMaxLineLength();
         int noRead = 0;
         boolean retry = true;
+        this.lastLineReadEnrichedByCarriageReturn = false;
         this.lastLineReadTerminatedByLineFeed = false;
         while (retry) {
             // attempt to find end of line (LF)
@@ -198,6 +200,9 @@ public class AS2SessionInputBuffer implements SessionInputBuffer, BufferInfo {
                 if (this.buffer[i] == HTTP.LF) {
                     pos = i;
                     this.lastLineReadTerminatedByLineFeed = true;
+                    if (i > 0 && this.buffer[i - 1] == HTTP.CR) {
+                        this.lastLineReadEnrichedByCarriageReturn = true;
+                    }
                     break;
                 }
             }
@@ -252,6 +257,10 @@ public class AS2SessionInputBuffer implements SessionInputBuffer, BufferInfo {
         return lastLineReadTerminatedByLineFeed;
     }
 
+    public boolean isLastLineReadEnrichedByCarriageReturn() {
+        return lastLineReadEnrichedByCarriageReturn;
+    }
+
     @Override
     public boolean isDataAvailable(int timeout) throws IOException {
         return hasBufferedData();
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
index 696c151d28f..022c9f04b1e 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
@@ -16,16 +16,28 @@
  */
 package org.apache.camel.component.as2.api;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
+import java.security.KeyStore;
 import java.security.SecureRandom;
 import java.security.Security;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.*;
 
+import com.helger.as2lib.client.AS2Client;
+import com.helger.as2lib.client.AS2ClientRequest;
+import com.helger.as2lib.client.AS2ClientResponse;
+import com.helger.as2lib.client.AS2ClientSettings;
+import com.helger.as2lib.crypto.ECompressionType;
+import com.helger.as2lib.crypto.ECryptoAlgorithmCrypt;
+import com.helger.as2lib.crypto.ECryptoAlgorithmSign;
+import com.helger.mail.cte.EContentTransferEncoding;
+import com.helger.security.keystore.EKeyStoreType;
 import org.apache.camel.component.as2.api.entity.AS2DispositionModifier;
 import org.apache.camel.component.as2.api.entity.AS2DispositionType;
 import org.apache.camel.component.as2.api.entity.AS2MessageDispositionNotificationEntity;
@@ -76,6 +88,8 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -84,6 +98,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 public class AS2MessageTest {
 
@@ -145,6 +160,10 @@ public class AS2MessageTest {
     private static X509Certificate signingCert;
     private static List<X509Certificate> certList;
 
+    private static File keystoreFile;
+
+    private static ApplicationEDIEntity ediEntity;
+
     private AS2SignedDataGenerator gen;
 
     @BeforeAll
@@ -169,6 +188,17 @@ public class AS2MessageTest {
         signingKP = kpg.generateKeyPair();
         signingCert = Utils.makeCertificate(signingKP, signingDN, issueKP, issueDN);
 
+        //
+        // initialize as2-lib keystore file
+        //
+        KeyStore ks = KeyStore.getInstance(EKeyStoreType.PKCS12.getID());
+        ks.load(null, "test".toCharArray());
+        ks.setKeyEntry("openas2a_alias", issueKP.getPrivate(), "test".toCharArray(), new X509Certificate[] { issueCert });
+        ks.setKeyEntry("openas2b_alias", signingKP.getPrivate(), "test".toCharArray(), new X509Certificate[] { signingCert });
+        keystoreFile = File.createTempFile("camel-as2", "keystore-p12");
+        keystoreFile.deleteOnExit();
+        ks.store(new FileOutputStream(keystoreFile), "test".toCharArray());
+
         certList = new ArrayList<>();
 
         certList.add(signingCert);
@@ -188,6 +218,7 @@ public class AS2MessageTest {
                     context.setAttribute(AS2ServerManager.SUBJECT, SUBJECT);
                     context.setAttribute(AS2ServerManager.FROM, AS2_NAME);
                     LOG.debug(AS2Utils.printMessage(request));
+                    ediEntity = HttpMessageUtils.extractEdiPayload(request, testServer.getDecryptingPrivateKey());
                 } catch (Exception e) {
                     throw new HttpException("Failed to parse AS2 Message Entity", e);
                 }
@@ -282,6 +313,52 @@ public class AS2MessageTest {
         assertTrue(ediEntity.isMainBody(), "Entity not set as main body of request");
     }
 
+    @ParameterizedTest
+    @CsvSource({
+            "false,false,false", "false,false,true", "false,true,false", "false,true,true", "true,false,false",
+            "true,false,true", "true,true,false", "true,true,true" })
+    void binaryContentTransferEncodingTest(boolean encrypt, boolean sign, boolean compress) {
+        // test with as2-lib because Camel AS2 client doesn't support binary content transfer encoding at the moment
+        // inspired from https://github.com/phax/as2-lib/wiki/Submodule-as2%E2%80%90lib#as2-client
+
+        // Start client configuration
+        final AS2ClientSettings aSettings = new AS2ClientSettings();
+        aSettings.setKeyStore(EKeyStoreType.PKCS12, keystoreFile, "test");
+
+        // Fixed sender
+        aSettings.setSenderData(AS2_NAME, FROM, "openas2a_alias");
+
+        // Fixed receiver
+        aSettings.setReceiverData(AS2_NAME, "openas2b_alias", "http://" + TARGET_HOST + ":" + TARGET_PORT + "/");
+        aSettings.setReceiverCertificate(issueCert);
+
+        // AS2 stuff
+        aSettings.setPartnershipName(aSettings.getSenderAS2ID() + "_" + aSettings.getReceiverAS2ID());
+
+        // Build client request
+        final AS2ClientRequest aRequest = new AS2ClientRequest("AS2 test message from as2-lib");
+        aRequest.setData(EDI_MESSAGE, StandardCharsets.US_ASCII);
+        aRequest.setContentType(AS2MediaType.APPLICATION_EDIFACT);
+
+        // reproduce https://issues.apache.org/jira/projects/CAMEL/issues/CAMEL-15111
+        aSettings.setEncryptAndSign(encrypt ? ECryptoAlgorithmCrypt.CRYPT_AES128_GCM : null,
+                sign ? ECryptoAlgorithmSign.DIGEST_SHA_512 : null);
+        if (compress) {
+            aSettings.setCompress(ECompressionType.ZLIB, false);
+        }
+        aRequest.setContentTransferEncoding(EContentTransferEncoding.BINARY);
+
+        // Send message
+        ediEntity = null;
+        final AS2ClientResponse aResponse = new AS2Client().sendSynchronous(aSettings, aRequest);
+
+        // Assertions
+        if (aResponse.hasException()) {
+            fail(aResponse.getException());
+        }
+        assertEquals(EDI_MESSAGE, ediEntity.getEdiMessage().replaceAll("\r", ""));
+    }
+
     @Test
     public void multipartSignedMessageTest() throws Exception {
         AS2ClientConnection clientConnection = new AS2ClientConnection(
diff --git a/components/camel-as2/pom.xml b/components/camel-as2/pom.xml
index 5bc35d5345b..9d6a1770b22 100644
--- a/components/camel-as2/pom.xml
+++ b/components/camel-as2/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-as2-parent</artifactId>
     <packaging>pom</packaging>
 
+    <properties>
+        <as2-lib-version>4.11.0</as2-lib-version>
+    </properties>
+
     <name>Camel :: AS2 :: Parent</name>
     <description>Camel AS2 parent</description>
 


[camel] 02/02: CAMEL-15111: Move as2-lib to parent

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-3.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 94afc38371d479a66b305231d97a381c8efdc158
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Dec 23 12:27:10 2022 +0100

    CAMEL-15111: Move as2-lib to parent
---
 camel-dependencies/pom.xml   | 1 +
 components/camel-as2/pom.xml | 4 ----
 parent/pom.xml               | 1 +
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/camel-dependencies/pom.xml b/camel-dependencies/pom.xml
index 5729e53362f..f6435005150 100644
--- a/camel-dependencies/pom.xml
+++ b/camel-dependencies/pom.xml
@@ -50,6 +50,7 @@
     <arquillian-jetty-embedded-9-version>1.0.0.CR3</arquillian-jetty-embedded-9-version>
     <arquillian-version>1.6.0.Final</arquillian-version>
     <arquillian-weld-embedded-version>2.0.0.Final</arquillian-weld-embedded-version>
+    <as2-lib-version>4.11.0</as2-lib-version>
     <ascii-table-version>1.8.0</ascii-table-version>
     <asm-version>8.0.1</asm-version>
     <asn1bean-version>1.13.0</asn1bean-version>
diff --git a/components/camel-as2/pom.xml b/components/camel-as2/pom.xml
index 9d6a1770b22..5bc35d5345b 100644
--- a/components/camel-as2/pom.xml
+++ b/components/camel-as2/pom.xml
@@ -29,10 +29,6 @@
     <artifactId>camel-as2-parent</artifactId>
     <packaging>pom</packaging>
 
-    <properties>
-        <as2-lib-version>4.11.0</as2-lib-version>
-    </properties>
-
     <name>Camel :: AS2 :: Parent</name>
     <description>Camel AS2 parent</description>
 
diff --git a/parent/pom.xml b/parent/pom.xml
index b9501b5c186..93806b58b45 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -67,6 +67,7 @@
         <arquillian-jetty-embedded-9-version>1.0.0.CR3</arquillian-jetty-embedded-9-version>
         <arquillian-version>1.6.0.Final</arquillian-version>
         <arquillian-weld-embedded-version>2.0.0.Final</arquillian-weld-embedded-version>
+        <as2-lib-version>4.11.0</as2-lib-version>
         <ascii-table-version>1.8.0</ascii-table-version>
         <asm-version>8.0.1</asm-version>
         <asn1bean-version>1.13.0</asn1bean-version>