This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch fix/as2-issues in repository https://gitbox.apache.org/repos/asf/camel.git
commit dba42d79f80a9ed1ac54b76e14a28efd4e1c3cbc Author: Guillaume Nodet <[email protected]> AuthorDate: Mon Mar 9 11:04:33 2026 +0100 CAMEL-23067: Capture raw request body for signature verification Store the raw (unparsed) request body bytes in AS2BHttpServerConnection before MIME parsing. This allows downstream handlers to verify signatures against the original bytes, which may differ from re-serialized entities due to header folding and whitespace normalization. Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../as2/api/io/AS2BHttpServerConnection.java | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2BHttpServerConnection.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2BHttpServerConnection.java index 8da0903c6979..ddd61ef68cb5 100644 --- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2BHttpServerConnection.java +++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/io/AS2BHttpServerConnection.java @@ -16,22 +16,37 @@ */ package org.apache.camel.component.as2.api.io; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import org.apache.camel.component.as2.api.entity.EntityParser; +import org.apache.camel.component.as2.api.util.EntityUtils; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.ContentLengthStrategy; +import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnection; import org.apache.hc.core5.http.io.HttpMessageParserFactory; import org.apache.hc.core5.http.io.HttpMessageWriterFactory; +import org.apache.hc.core5.http.io.entity.BasicHttpEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class AS2BHttpServerConnection extends DefaultBHttpServerConnection { + private static final Logger LOG = LoggerFactory.getLogger(AS2BHttpServerConnection.class); + + /** + * The raw (unparsed) request body bytes captured before MIME parsing. This allows downstream handlers to perform + * signature verification against the original bytes, which may differ from the re-serialized parsed entity due to + * MIME header folding, whitespace normalization, and line ending changes. + */ + private byte[] rawRequestBody; + public AS2BHttpServerConnection(Http1Config http1Config) { this(http1Config, null, null); } @@ -53,9 +68,32 @@ public class AS2BHttpServerConnection extends DefaultBHttpServerConnection { outgoingContentStrategy, requestParserFactory, responseWriterFactory); } + /** + * Returns the raw (unparsed) request body bytes captured before MIME parsing. + * + * @return the raw body bytes, or null if no entity was received + */ + public byte[] getRawRequestBody() { + return rawRequestBody; + } + @Override public void receiveRequestEntity(ClassicHttpRequest request) throws HttpException, IOException { super.receiveRequestEntity(request); + // Capture raw body bytes before parsing modifies them. + // This is essential for signature verification of async MDNs, where the parsed + // MIME entity may have different bytes due to header folding and whitespace normalization. + if (request.getEntity() != null) { + try { + rawRequestBody = EntityUtils.getContent(request.getEntity()); + // Reset the entity with the captured bytes so it can be parsed + ContentType contentType = ContentType.parse(request.getEntity().getContentType()); + request.setEntity( + new BasicHttpEntity(new ByteArrayInputStream(rawRequestBody), rawRequestBody.length, contentType)); + } catch (Exception e) { + LOG.debug("Failed to capture raw request body bytes", e); + } + } EntityParser.parseAS2MessageEntity(request); }
