Andrea Cosentino created CAMEL-24429:
----------------------------------------

             Summary: camel-as2 - per-request security material outlives the 
request in ResponseMDN and the listener context
                 Key: CAMEL-24429
                 URL: https://issues.apache.org/jira/browse/CAMEL-24429
             Project: Camel
          Issue Type: Bug
          Components: camel-as2
            Reporter: Andrea Cosentino
            Assignee: Andrea Cosentino
             Fix For: 4.23.0


Two places keep per-request state where it can be observed by a later or 
concurrent request.

*ResponseMDN* holds the security material in mutable instance fields and 
overwrites them per request:

{code:java}
private AS2SignatureAlgorithm signingAlgorithm;
private Certificate[] signingCertificateChain;
private PrivateKey signingPrivateKey;
private PrivateKey decryptingPrivateKey;
private Certificate[] validateSigningCertificateChain;
private boolean keysAreDynamic = false;
...
if (this.keysAreDynamic) {
    this.signingAlgorithm = (AS2SignatureAlgorithm) 
context.getAttribute(AS2ServerConnection.AS2_SIGNING_ALGORITHM);
    this.signingCertificateChain = (Certificate[]) 
context.getAttribute(...AS2_SIGNING_CERTIFICATE_CHAIN);
    this.signingPrivateKey = (PrivateKey) 
context.getAttribute(...AS2_SIGNING_PRIVATE_KEY);
    this.decryptingPrivateKey = (PrivateKey) 
context.getAttribute(...AS2_DECRYPTING_PRIVATE_KEY);
    this.validateSigningCertificateChain = (Certificate[]) 
context.getAttribute(...AS2_VALIDATE_SIGNING_CERTIFICATE_CHAIN);
}
{code}

The instance is registered once on the shared HttpProcessor, so it is shared 
across requests. The assignment block is not inside the class's lock, and the 
values persist after the request that set them. A deployment hosting two 
partners on different paths with different keys can therefore have one 
request's MDN signed with the other partner's key.

*AS2ServerConnection* creates the HttpContext once outside the request loop:

{code:java}
final HttpContext context = HttpCoreContext.create();
try {
    while (!Thread.interrupted()) {
        this.httpService.handleRequest(this.serverConnection, context);
        ...
        String recipientAddress = 
coreContext.getAttribute(AS2AsynchronousMDNManager.RECIPIENT_ADDRESS, 
String.class);
{code}

RECIPIENT_ADDRESS and ASYNCHRONOUS_MDN set while handling one request are still 
present on the next iteration, so a later request that does not request an 
asynchronous MDN can trigger a resend to the previous request's address.

Proposal: keep the dynamically loaded keys and chains in local variables (or in 
the HttpCoreContext) for the duration of process() rather than in instance 
fields, and remove RECIPIENT_ADDRESS/ASYNCHRONOUS_MDN from the context after 
the send block - or create a fresh context per request. A test that drives two 
requests with different key material through one connection would cover both.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to