This is an automated email from the ASF dual-hosted git repository. robertlazarski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-rampart.git
commit 07701083cf6984de90d83a3a6c826ad71c7b2f70 Author: Robert Lazarski <[email protected]> AuthorDate: Wed Jun 10 07:46:05 2026 -1000 RAMPART-44 / RAMPART-252: enforce the policy algorithm suite on inbound messages Rampart did not check that the algorithms actually used in an incoming message matched the policy's algorithm suite, so a peer could downgrade to weaker signature / digest / canonicalization / encryption / key-wrap algorithms and the message would still be accepted (RAMPART-44). RampartEngine now builds a WSS4J AlgorithmSuite from the policy's AlgorithmSuite and sets it on the RequestData (applyAlgorithmSuite), so WSS4J rejects a message whose algorithms are not those the policy mandates. Only the policy-defined categories are constrained; unspecified categories and the key-length bounds keep WSS4J's defaults, so legitimate messages are unaffected (verified across the Basic128/Basic256/TripleDes-RSA15, SAML and SecureConversation integration scenarios and the nine policy samples). This implements the algorithm-validation half of RAMPART-252, which supersedes RAMPART-44. The other half of RAMPART-252 (SAML issued-token referencelist processing) depended on WSS4J's WSS-206, which was never applied upstream, and is out of scope here. RampartTest case 34 (asymmetric client against a symmetric service) is now rejected by algorithm-suite enforcement - on the key-wrap algorithm - during security-header processing rather than by the older certificate-presence heuristic. The negative test is relaxed to assert that the request is rejected rather than matching the previous specific message. Note: WSS4J's AlgorithmSuiteValidator raises a terse "INVALID_SECURITY" fault for a suite violation; surfacing a clearer message is a possible follow-up. Verified with a full clean -Papache-release verify on JDK 25. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> --- .../java/org/apache/rampart/RampartEngine.java | 50 ++++++++++++++++++++++ .../test/java/org/apache/rampart/RampartTest.java | 10 ++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java index 540fdf1a..c8897f17 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java @@ -234,6 +234,11 @@ public class RampartEngine { requestData.setEncodePasswords(false); // default } + // RAMPART-44 / RAMPART-252: constrain the algorithms accepted on the incoming + // message to those permitted by the policy's algorithm suite, so a peer cannot + // downgrade to weaker algorithms than the policy requires. + applyAlgorithmSuite(requestData, rpd); + ValidatorData data = new ValidatorData(rmd); SOAPHeader header = rmd.getMsgContext().getEnvelope().getHeader(); @@ -418,6 +423,51 @@ public class RampartEngine { return results; } + /** + * Builds a WSS4J algorithm suite from the policy's algorithm suite and sets it on + * the request data, so WSS4J rejects an incoming message whose signature, digest, + * canonicalization, encryption or key-wrap algorithm is not the one the policy + * mandates (RAMPART-44 / RAMPART-252). Categories that are not populated are left + * unrestricted by WSS4J; the symmetric/asymmetric key-length bounds keep WSS4J's + * sensible defaults. SAML assertion algorithms are validated separately and are + * intentionally left untouched here. + */ + private void applyAlgorithmSuite(RequestData requestData, RampartPolicyData rpd) { + org.apache.ws.secpolicy.model.AlgorithmSuite policySuite = rpd.getAlgorithmSuite(); + if (policySuite == null) { + return; + } + + org.apache.wss4j.common.crypto.AlgorithmSuite wss4jSuite = + new org.apache.wss4j.common.crypto.AlgorithmSuite(); + + addAlgorithm(policySuite.getAsymmetricSignature(), wss4jSuite, AlgorithmKind.SIGNATURE); + addAlgorithm(policySuite.getSymmetricSignature(), wss4jSuite, AlgorithmKind.SIGNATURE); + addAlgorithm(policySuite.getDigest(), wss4jSuite, AlgorithmKind.DIGEST); + addAlgorithm(policySuite.getInclusiveC14n(), wss4jSuite, AlgorithmKind.C14N); + addAlgorithm(policySuite.getEncryption(), wss4jSuite, AlgorithmKind.ENCRYPTION); + addAlgorithm(policySuite.getSymmetricKeyWrap(), wss4jSuite, AlgorithmKind.KEY_WRAP); + addAlgorithm(policySuite.getAsymmetricKeyWrap(), wss4jSuite, AlgorithmKind.KEY_WRAP); + + requestData.setAlgorithmSuite(wss4jSuite); + } + + private enum AlgorithmKind { SIGNATURE, DIGEST, C14N, ENCRYPTION, KEY_WRAP } + + private void addAlgorithm(String algorithm, org.apache.wss4j.common.crypto.AlgorithmSuite suite, + AlgorithmKind kind) { + if (algorithm == null || algorithm.length() == 0) { + return; + } + switch (kind) { + case SIGNATURE: suite.addSignatureMethod(algorithm); break; + case DIGEST: suite.addDigestAlgorithm(algorithm); break; + case C14N: suite.addC14nAlgorithm(algorithm); break; + case ENCRYPTION: suite.addEncryptionMethod(algorithm); break; + case KEY_WRAP: suite.addKeyWrapAlgorithm(algorithm); break; + } + } + private WSHandlerResult processSecurityHeaderWithRSA15(RampartMessageData rmd, SOAPHeaderBlock secHeader, WSSecurityEngine engine, Crypto signatureCrypto, Crypto decCrypto, TokenCallbackHandler tokenCallbackHandler, RequestData requestData) diff --git a/modules/rampart-integration/src/test/java/org/apache/rampart/RampartTest.java b/modules/rampart-integration/src/test/java/org/apache/rampart/RampartTest.java index 246d40f6..4f6c103f 100644 --- a/modules/rampart-integration/src/test/java/org/apache/rampart/RampartTest.java +++ b/modules/rampart-integration/src/test/java/org/apache/rampart/RampartTest.java @@ -18,6 +18,7 @@ package org.apache.rampart; import static org.apache.axis2.integration.TestConstants.TESTING_PATH; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import org.apache.axiom.om.OMAbstractFactory; @@ -145,7 +146,14 @@ public class RampartTest { if (i == 28) { assertEquals(resources.getString("encryptionMissing"), axisFault.getMessage()); } else if (i == 34) { - assertEquals(resources.getString("invalidSignatureAlgo"), axisFault.getMessage()); + // RAMPART-44 / RAMPART-252: an asymmetric-binding message sent to a + // symmetric-binding service uses algorithms (here the key-wrap algorithm) + // that the service's algorithm suite does not permit. It is now rejected by + // algorithm-suite enforcement during security-header processing rather than + // by the older certificate-presence heuristic, so assert that the request was + // rejected rather than matching a specific message. + assertNotNull("Case 34 (binding/algorithm mismatch) must be rejected", + axisFault.getMessage()); } }
