diff --git a/pom.xml b/pom.xml index 2987e2f529..ea86596466 100644 --- a/pom.xml +++ b/pom.xml @@ -541,6 +541,7 @@ 1.8 2.8 5.2.4 + 3.3.0 info @@ -577,6 +578,12 @@ ${junit.version} test + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + org.xmlunit xmlunit-core @@ -646,6 +653,12 @@ 0.7.2 test + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + diff --git a/src/main/java/org/apache/xml/security/resource/xmlsecurity_de.properties b/src/main/java/org/apache/xml/security/resource/xmlsecurity_de.properties index 03a2369566..34539047ea 100644 --- a/src/main/java/org/apache/xml/security/resource/xmlsecurity_de.properties +++ b/src/main/java/org/apache/xml/security/resource/xmlsecurity_de.properties @@ -189,11 +189,13 @@ stax.unsupportedKeyTransp = Der public-key Algorithmus ist zu kurz um den symmet stax.recursiveKeyReference = Rekursive Schl\u00fcssel referenzierung detektiert. stax.ecParametersNotSupported = ECParameters werden nicht unterst\u00fctzt. stax.namedCurveMissing = NamedCurve fehlt. -stax.encryption.securePartNotFound = Part zum Verschl\u00fcsseln nicht gefunden: {0} -stax.signature.securePartNotFound = Part zum Signieren nicht gefunden: {0} -stax.multipleSignaturesNotSupported = Mehrere Signaturen werden nicht unterstützt. +stax.encryption.tooFewOccurrences = Zu wenige ({0}/{1}) Elemente gefunden zum Verschl\u00fcsslen: {2} +stax.encryption.tooManyOccurrences = Zu viele ({0}/{1}) Elemente gefunden zum Verschl\u00fcsslen: {2} +stax.signature.tooFewOccurrences = Zu wenige ({0}/{1}) Elemente gefunden zum Signieren: {2} +stax.signature.tooManyOccurrences = Zu viele ({0}/{1}) Elemente gefunden zum Signieren: {2} +stax.multipleSignaturesNotSupported = Mehrere Signaturen werden nicht unterst\u00fctzt. stax.signature.keyNameMissing = KeyName nicht konfiguriert. -stax.keyNotFoundForName = Kein Schl\u00fcssel für Schl\u00fcsselname konfiguriert: {0} +stax.keyNotFoundForName = Kein Schl\u00fcssel f\u00fcr Schl\u00fcsselname konfiguriert: {0} stax.keyTypeNotSupported = Key vom Typ {0} nicht f\u00fcr einen Key-Namenssuche unterst\u00fctzt stax.idsetbutnotgenerated = An Id attribute is specified, but Id generation is disabled stax.idgenerationdisablewithmultipleparts = Id generation must not be disabled when multiple parts need signing \ No newline at end of file diff --git a/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties b/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties index adb3146488..e9734547ab 100644 --- a/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties +++ b/src/main/java/org/apache/xml/security/resource/xmlsecurity_en.properties @@ -189,8 +189,10 @@ stax.unsupportedKeyTransp = public key algorithm too weak to encrypt symmetric k stax.recursiveKeyReference = Recursive key reference detected. stax.ecParametersNotSupported = ECParameters not supported. stax.namedCurveMissing = NamedCurve is missing. -stax.encryption.securePartNotFound = Part to encrypt not found: {0} -stax.signature.securePartNotFound = Part to sign not found: {0} +stax.encryption.tooFewOccurrences = Too few ({0}/{1}) elements found to encrypt: {2} +stax.encryption.tooManyOccurrences = Too many ({0}/{1}) elements found to encrypt: {2} +stax.signature.tooFewOccurrences = Too few ({0}/{1}) elements found to sign: {2} +stax.signature.tooManyOccurrences = Too many ({0}/{1}) elements found to sign: {2} stax.multipleSignaturesNotSupported = Multiple signatures are not supported. stax.signature.keyNameMissing = KeyName not configured. stax.keyNotFoundForName = No key configured for KeyName: {0} diff --git a/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java index 4603d03a0c..b8d14e4390 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java @@ -22,12 +22,10 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; @@ -37,6 +35,7 @@ import org.apache.xml.security.stax.ext.stax.XMLSecEventFactory; import org.apache.xml.security.stax.ext.stax.XMLSecNamespace; import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.utils.KeyValue; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -230,24 +229,25 @@ protected void outputAsEvent(OutputProcessorChain outputProcessorChain, XMLSecEv outputProcessorChain.processEvent(xmlSecEvent); } - protected SecurePart securePartMatches(XMLSecStartElement xmlSecStartElement, - OutputProcessorChain outputProcessorChain, String dynamicParts) { - Map dynamicSecureParts = outputProcessorChain.getSecurityContext().getAsMap(dynamicParts); - return securePartMatches(xmlSecStartElement, dynamicSecureParts); + protected KeyValue securePartMatches(XMLSecStartElement xmlSecStartElement, + OutputProcessorChain outputProcessorChain, + String dynamicPartSelectors) { + OutboundSecurityContext securityContext = outputProcessorChain.getSecurityContext(); + List dynamicSecurePartSelectors = securityContext.get(dynamicPartSelectors); + return securePartMatches(xmlSecStartElement, dynamicSecurePartSelectors); } - protected SecurePart securePartMatches(XMLSecStartElement xmlSecStartElement, Map secureParts) { - SecurePart securePart = null; - if (secureParts != null) { - securePart = secureParts.get(xmlSecStartElement.getName()); - if (securePart == null) { - Attribute attribute = xmlSecStartElement.getAttributeByName(securityProperties.getIdAttributeNS()); - if (attribute != null) { - securePart = secureParts.get(attribute.getValue()); + protected KeyValue securePartMatches(XMLSecStartElement xmlSecStartElement, + List securePartSelectors) { + if (securePartSelectors != null) { + for (SecurePartSelector securePartSelector : securePartSelectors) { + SecurePart securePart = securePartSelector.select(xmlSecStartElement); + if (securePart != null) { + return new KeyValue<>(securePartSelector, securePart); } } } - return securePart; + return null; } protected void outputDOMElement(Element element, OutputProcessorChain outputProcessorChain) diff --git a/src/main/java/org/apache/xml/security/stax/ext/ByAttributeElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/ByAttributeElementSelector.java new file mode 100644 index 0000000000..f66a80a11d --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/ByAttributeElementSelector.java @@ -0,0 +1,48 @@ +package org.apache.xml.security.stax.ext; + +import java.util.function.Supplier; + +import javax.xml.namespace.QName; +import javax.xml.stream.events.Attribute; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +import static java.util.Objects.requireNonNull; + +/** + * Selects an element to secure based on a given value of a supplied attribute name. + */ +public class ByAttributeElementSelector implements ElementSelector { + + private final Supplier nameSupplier; + private final String value; + + ByAttributeElementSelector(Supplier nameSupplier, String value) { + requireNonNull(value, "value is null"); + this.nameSupplier = nameSupplier; + this.value = value; + } + + public ByAttributeElementSelector(QName name, String value) { + this(() -> name, value); + } + + @Override + public boolean select(XMLSecStartElement element) { + if (element != null) { + QName name = nameSupplier.get(); + if (name != null) { + Attribute attribute = element.getAttributeByName(name); + if (attribute != null && value.equals(attribute.getValue())) { + return true; + } + } + } + return false; + } + + @Override + public String toString() { + return "//*[@" + nameSupplier.get() + "='" + value + "']"; + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/ByNameElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/ByNameElementSelector.java new file mode 100644 index 0000000000..a27aedfee2 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/ByNameElementSelector.java @@ -0,0 +1,30 @@ +package org.apache.xml.security.stax.ext; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +import static java.util.Objects.requireNonNull; + +/** + * This class selects XML elements by name. + */ +public class ByNameElementSelector implements ElementSelector { + + private final QName name; + + public ByNameElementSelector(QName name) { + requireNonNull(name, "name is null"); + this.name = name; + } + + @Override + public boolean select(XMLSecStartElement element) { + return element != null && element.getName().equals(name); + } + + @Override + public String toString() { + return "//" + name; + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/DocumentElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/DocumentElementSelector.java new file mode 100644 index 0000000000..16da9491d5 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/DocumentElementSelector.java @@ -0,0 +1,32 @@ +package org.apache.xml.security.stax.ext; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +/** + * This singleton selects the document element. + */ +public class DocumentElementSelector implements ElementSelector { + + private static class LazilyLoaded { + + @SuppressWarnings("PMD.AccessorClassGeneration") + private static final DocumentElementSelector INSTANCE = new DocumentElementSelector(); + } + + private DocumentElementSelector() { + } + + @Override + public boolean select(XMLSecStartElement element) { + return element == null; + } + + @Override + public String toString() { + return "/"; + } + + public static DocumentElementSelector getInstance() { + return LazilyLoaded.INSTANCE; + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/ElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/ElementSelector.java new file mode 100644 index 0000000000..088af81aba --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/ElementSelector.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.xml.security.stax.ext; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +/** + * This interface allows implementors to select which elements to secure, based on an element's qualified name + * and skeleton DOM element. + */ +public interface ElementSelector { + + /** + * Selects a given element for securing, or {@code null} to indicate the document element (the document as a whole). + * In practice, the element {@code null} is used to select secure parts that define external references to be + * digested. + * + * @param element The element to select, possibly {@code null}. + * @return {@code true} to select the given element for securing, {@code false} otherwise. + */ + boolean select(XMLSecStartElement element); +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/ElementSelectorFactory.java b/src/main/java/org/apache/xml/security/stax/ext/ElementSelectorFactory.java new file mode 100644 index 0000000000..2d571fed19 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/ElementSelectorFactory.java @@ -0,0 +1,6 @@ +package org.apache.xml.security.stax.ext; + +public interface ElementSelectorFactory { + + ElementSelector createElementSelector(); +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/InboundXMLSec.java b/src/main/java/org/apache/xml/security/stax/ext/InboundXMLSec.java index 9be3930f17..5697fa64aa 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/InboundXMLSec.java +++ b/src/main/java/org/apache/xml/security/stax/ext/InboundXMLSec.java @@ -115,7 +115,7 @@ public XMLStreamReader processInMessage( requestSecurityEvents = Collections.emptyList(); } - final InboundSecurityContextImpl inboundSecurityContext = new InboundSecurityContextImpl(); + final InboundSecurityContextImpl inboundSecurityContext = new InboundSecurityContextImpl(securityProperties); inboundSecurityContext.putList(SecurityEvent.class, requestSecurityEvents); inboundSecurityContext.addSecurityEventListener(securityEventListener); diff --git a/src/main/java/org/apache/xml/security/stax/ext/NoElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/NoElementSelector.java new file mode 100644 index 0000000000..c6ab79cb38 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/NoElementSelector.java @@ -0,0 +1,29 @@ +package org.apache.xml.security.stax.ext; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +public class NoElementSelector implements ElementSelector { + + private static class LazilyLoaded { + + @SuppressWarnings("PMD.AccessorClassGeneration") + private static final NoElementSelector INSTANCE = new NoElementSelector(); + } + + private NoElementSelector() { + } + + @Override + public boolean select(XMLSecStartElement element) { + return false; + } + + @Override + public String toString() { + return ""; + } + + public static NoElementSelector getInstance() { + return LazilyLoaded.INSTANCE; + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/OutboundXMLSec.java b/src/main/java/org/apache/xml/security/stax/ext/OutboundXMLSec.java index 6cd5b918a5..f651966af0 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/OutboundXMLSec.java +++ b/src/main/java/org/apache/xml/security/stax/ext/OutboundXMLSec.java @@ -94,7 +94,7 @@ public XMLStreamWriter processOutMessage(XMLStreamWriter xmlStreamWriter, String private XMLStreamWriter processOutMessage( Object output, String encoding, SecurityEventListener eventListener) throws XMLSecurityException { - final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl(); + final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl(securityProperties); if (eventListener != null) { outboundSecurityContext.addSecurityEventListener(eventListener); @@ -105,64 +105,27 @@ private XMLStreamWriter processOutMessage( OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(outboundSecurityContext, documentContext); - SecurePart signEntireRequestPart = null; - SecurePart encryptEntireRequestPart = null; - for (XMLSecurityConstants.Action action : securityProperties.getActions()) { if (XMLSecurityConstants.SIGNATURE.equals(action)) { XMLSignatureOutputProcessor signatureOutputProcessor = new XMLSignatureOutputProcessor(); initializeOutputProcessor(outputProcessorChain, signatureOutputProcessor, action); configureSignatureKeys(outboundSecurityContext); - List signatureParts = securityProperties.getSignatureSecureParts(); - for (SecurePart securePart : signatureParts) { - if (securePart.getIdToSecure() == null && securePart.getName() != null) { - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.SIGNATURE_PARTS, - securePart.getName(), - securePart - ); - } else if (securePart.getIdToSecure() != null) { - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.SIGNATURE_PARTS, - securePart.getIdToSecure(), - securePart - ); - } else if (securePart.getExternalReference() != null) { - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.SIGNATURE_PARTS, - securePart.getExternalReference(), - securePart - ); - } else if (securePart.isSecureEntireRequest()) { - // Special functionality to sign the first element in the request - signEntireRequestPart = securePart; - } - } + List signaturePartSelectors = securityProperties.getSignaturePartSelectors(); + outputProcessorChain.getSecurityContext().put( + XMLSecurityConstants.SIGNATURE_PART_SELECTORS, + signaturePartSelectors + ); } else if (XMLSecurityConstants.ENCRYPTION.equals(action)) { XMLEncryptOutputProcessor encryptOutputProcessor = new XMLEncryptOutputProcessor(); initializeOutputProcessor(outputProcessorChain, encryptOutputProcessor, action); configureEncryptionKeys(outboundSecurityContext); - List encryptionParts = securityProperties.getEncryptionSecureParts(); - for (SecurePart securePart : encryptionParts) { - if (securePart.getIdToSecure() == null && securePart.getName() != null) { - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.ENCRYPTION_PARTS, - securePart.getName(), - securePart - ); - } else if (securePart.getIdToSecure() != null) { - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.ENCRYPTION_PARTS, - securePart.getIdToSecure(), - securePart - ); - } else if (securePart.isSecureEntireRequest()) { - // Special functionality to encrypt the first element in the request - encryptEntireRequestPart = securePart; - } - } + List encryptionPartSelectors = securityProperties.getEncryptionPartSelectors(); + outputProcessorChain.getSecurityContext().put( + XMLSecurityConstants.ENCRYPTION_PART_SELECTORS, + encryptionPartSelectors + ); } } if (output instanceof OutputStream) { @@ -177,11 +140,7 @@ private XMLStreamWriter processOutMessage( throw new IllegalArgumentException(output + " is not supported as output"); } - XMLSecurityStreamWriter streamWriter = new XMLSecurityStreamWriter(outputProcessorChain); - streamWriter.setSignEntireRequestPart(signEntireRequestPart); - streamWriter.setEncryptEntireRequestPart(encryptEntireRequestPart); - - return streamWriter; + return new XMLSecurityStreamWriter(outputProcessorChain); } private void initializeOutputProcessor(OutputProcessorChainImpl outputProcessorChain, OutputProcessor outputProcessor, XMLSecurityConstants.Action action) throws XMLSecurityException { diff --git a/src/main/java/org/apache/xml/security/stax/ext/RootElementSelector.java b/src/main/java/org/apache/xml/security/stax/ext/RootElementSelector.java new file mode 100644 index 0000000000..18e8bbd328 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/RootElementSelector.java @@ -0,0 +1,33 @@ +package org.apache.xml.security.stax.ext; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +/** + * Selects the root element as the element to secure. + * This replaces {@link SecurePart#setSecureEntireRequest(boolean)}. + */ +public class RootElementSelector implements ElementSelector { + + private static final class LazilyLoaded { + + @SuppressWarnings("PMD.AccessorClassGeneration") + private static final RootElementSelector INSTANCE = new RootElementSelector(); + } + + private RootElementSelector() { + } + + @Override + public boolean select(XMLSecStartElement element) { + return element != null && element.getParentXMLSecStartElement() == null; + } + + @Override + public String toString() { + return "/*"; + } + + public static RootElementSelector getInstance() { + return LazilyLoaded.INSTANCE; + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/SecurePart.java b/src/main/java/org/apache/xml/security/stax/ext/SecurePart.java index 42586b3276..6542c7c641 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/SecurePart.java +++ b/src/main/java/org/apache/xml/security/stax/ext/SecurePart.java @@ -18,14 +18,18 @@ */ package org.apache.xml.security.stax.ext; +import org.apache.xml.security.stax.ext.XMLSecurityProperties.SecurePartSelectorBuilder; + import javax.xml.namespace.QName; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; /** - * Class to describe which and how an element must be secured - * + * Class to describe which and how an element must be secured. + * The "which" is deprecated in favor of a dedicated and more flexible {@link ElementSelector}, and is only supported + * for backward compatibility. + * The "how" is the sole and dedicated purpose of this class. */ public class SecurePart { @@ -108,7 +112,10 @@ public SecurePart(String externalReference, String[] transforms, String digestMe } /** - * The name of the element to be secured + * The name of the element to be secured. + * The framework now uses {@link ElementSelector#select(javax.xml.stream.events.StartElement)} + * instead to define which element(s) to secure. + * This method is only supported for backward compatibility. * * @return The Element-Local-Name */ @@ -116,6 +123,11 @@ public QName getName() { return name; } + /** + * Sets which element to secure based on a given qualified name. + * Consider {@link XPathElementSelector} with an expression such as "//local-name" instead, or a more complex expression + * such as "//*[namespace-uri() = 'urn:ns0' and local-name() = 'element']" when you need to match namespaces. + */ public void setName(QName name) { this.name = name; } @@ -132,6 +144,8 @@ public void setModifier(Modifier modifier) { * The ID of the element to secure (encrypt or sign), possibly {@code null}. * This matches the attribute value of an element that has an attribute with a name given by * {@link XMLSecurityProperties#getIdAttributeNS()}. + * The framework now uses {@link ElementSelector#select(org.apache.xml.security.stax.ext.stax.XMLSecStartElement)} + * instead to define which element(s) to secure. * * @return The ID of the element to secure, possibly {@code null}. */ @@ -139,6 +153,10 @@ public String getIdToSecure() { return idToSecure; } + /** + * Sets which element to secure based on a given attribute value. + * Consider using {@link ByAttributeElementSelector} instead. + */ public void setIdToSecure(String idToSecure) { this.idToSecure = idToSecure; } @@ -153,7 +171,6 @@ public String getIdToSign() { /** * Use {@link #setIdToSecure(String)} instead. - * @param idToSign */ @Deprecated public void setIdToSign(String idToSign) { @@ -192,19 +209,51 @@ public void setDigestMethod(String digestMethod) { this.digestMethod = digestMethod; } + /** + * If this secure part is required or not. + * The framework now uses {@link SecurePartSelector#getRequiredNumOccurrences()} instead. + * This method is only supported for backward compatibility. + */ public boolean isRequired() { return required; } + /** + * Sets if this element is required, which is {@code true} by default. + * Consider using {@link SecurePartSelectorBuilder#requireNumOccurrences(int)} instead, with a value of {@code 1} (required) or + * {@code -1} (not required). + */ public void setRequired(boolean required) { this.required = required; } + /** + * If the entire request is to be secured. + * The framework now uses {@link ElementSelector#select(org.apache.xml.security.stax.ext.stax.XMLSecStartElement)} + * instead to define which element(s) to secure. + */ public boolean isSecureEntireRequest() { return secureEntireRequest; } + /** + * Sets if the entire request is to be secured. + * Setting this to {@code true} is equivalent to selecting the root element. + * Consider using {@link RootElementSelector} instead. + */ public void setSecureEntireRequest(boolean secureEntireRequest) { this.secureEntireRequest = secureEntireRequest; } + + @Override + public String toString() { + if (idToSecure != null) { + return idToSecure; + } else if (name != null) { + return name.toString(); + } else if (externalReference != null) { + return externalReference; + } + return super.toString(); + } } diff --git a/src/main/java/org/apache/xml/security/stax/ext/SecurePartFactory.java b/src/main/java/org/apache/xml/security/stax/ext/SecurePartFactory.java new file mode 100644 index 0000000000..4414d72a5c --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/SecurePartFactory.java @@ -0,0 +1,58 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.xml.security.stax.ext; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.w3c.dom.Element; + +import javax.xml.namespace.QName; + +/** + * This interface allows implementations to create a secure for a selected element. + * An example of a typical implementation: + *
+ * {@code
+ * SecurePartFactory securePartFactory = (name, element) -> new SecurePart(name, SecurePart.Modifier.Content);
+ * }
+ * 
+ * + * @see ElementSelector + */ +public interface SecurePartFactory { + + /** + * Creates a secure part given a selected element. + * The framework calls this method whenever {@link ElementSelector#select(QName, Element)} returns {@code true}. + * The selected element is defined by a qualified name and a skeleton DOM element, which have the same values as + * what passes {@link ElementSelector#select(QName, Element)}. + * If a selector for example never selects any elements with {@code null} name or {@code null} skeleton DOM element, + * then the corresponding factory will never be called with such values either. + * Implementations should return a secure part containing instructions how to secure the element. + *

+ * Implementations may return {@code null} to deselect the element after all, overriding the element selector's + * decision. + *

+ * + * @param name The qualified name, possibly {@code null}. + * @param element The skeleton DOM element, possibly {@code null}. + * @return A secure part, or {@code null} to skip this element after all. + * @see ElementSelector#select(QName, Element) + */ + SecurePart createSecurePart(XMLSecStartElement element); +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/SecurePartSelector.java b/src/main/java/org/apache/xml/security/stax/ext/SecurePartSelector.java new file mode 100644 index 0000000000..fcaba058b6 --- /dev/null +++ b/src/main/java/org/apache/xml/security/stax/ext/SecurePartSelector.java @@ -0,0 +1,71 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.xml.security.stax.ext; + +import java.util.List; +import java.util.function.Supplier; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; + +import static java.util.Objects.requireNonNull; + +/** + * This class is used by the framework to group an element selector, a secure part factory and a required number of + * occurrences. + * It is not intended to be used by callers of the framework, hence the package-private constructor. + */ +public class SecurePartSelector { + + private final Supplier> actionsSupplier; + private final ElementSelector elementSelector; + private final SecurePartFactory securePartFactory; + private final int requiredNumOccurrences; + + SecurePartSelector(Supplier> actionsSupplier, ElementSelector elementSelector, SecurePartFactory securePartFactory, int requiredNumOccurrences) { + requireNonNull(actionsSupplier, "actions supplier is null"); + requireNonNull(elementSelector, "element selector is null"); + requireNonNull(securePartFactory, "secure part factory is null"); + this.actionsSupplier = actionsSupplier; + this.elementSelector = elementSelector; + this.securePartFactory = securePartFactory; + this.requiredNumOccurrences = requiredNumOccurrences; + } + + public List getActions() { + List actions = actionsSupplier.get(); + requireNonNull(actions, "actions is null"); + return actions; + } + + public int getRequiredNumOccurrences() { + return requiredNumOccurrences; + } + + public SecurePart select(XMLSecStartElement element) { + if (elementSelector.select(element)) { + return securePartFactory.createSecurePart(element); + } + return null; + } + + @Override + public String toString() { + return elementSelector.toString(); + } +} diff --git a/src/main/java/org/apache/xml/security/stax/ext/SecurityContext.java b/src/main/java/org/apache/xml/security/stax/ext/SecurityContext.java index 1d303bb311..5bc2329c08 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/SecurityContext.java +++ b/src/main/java/org/apache/xml/security/stax/ext/SecurityContext.java @@ -21,11 +21,13 @@ import org.apache.xml.security.stax.securityEvent.SecurityEventListener; import java.util.List; -import java.util.Map; /** */ public interface SecurityContext extends SecurityEventListener { + + XMLSecurityProperties getSecurityProperties(); + void put(String key, T value); T get(String key); @@ -34,14 +36,6 @@ public interface SecurityContext extends SecurityEventListener { void putList(Object key, T value); - void putAsList(Object key, T value); - - List getAsList(Object key); - - void putAsMap(Object key, T mapKey, U mapValue); - - Map getAsMap(Object key); - /** * Registers a SecurityEventListener to receive Security-Events * diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSec.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSec.java index 8980057d31..c8a219eacb 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/XMLSec.java +++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSec.java @@ -23,6 +23,7 @@ import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.RSAPrivateKey; import java.util.HashSet; +import java.util.List; import javax.crypto.SecretKey; import javax.xml.bind.JAXBContext; @@ -137,7 +138,8 @@ public static XMLSecurityProperties validateAndApplyDefaultsToOutboundSecurityPr throw new XMLSecurityConfigurationException("stax.idsetbutnotgenerated"); } - if (securityProperties.getSignatureSecureParts() != null && securityProperties.getSignatureSecureParts().size() > 1 && !securityProperties.isSignatureGenerateIds()) { + List signaturePartSelectors = securityProperties.getSignaturePartSelectors(); + if (signaturePartSelectors != null && signaturePartSelectors.size() > 1 && !securityProperties.isSignatureGenerateIds()) { throw new XMLSecurityConfigurationException("stax.idgenerationdisablewithmultipleparts"); } diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java index 75485a1d53..c98f9e9e5d 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java +++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java @@ -257,8 +257,8 @@ public enum DIRECTION { public static final String PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION = "PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION"; public static final String PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY = "PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY"; - public static final String SIGNATURE_PARTS = "signatureParts"; - public static final String ENCRYPTION_PARTS = "encryptionParts"; + public static final String SIGNATURE_PART_SELECTORS = "signaturePartSelectors"; + public static final String ENCRYPTION_PART_SELECTORS = "encryptionPartSelectors"; public static final Action SIGNATURE = new Action("Signature"); public static final Action ENCRYPTION = new Action("Encryption"); diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java index 8ee89f448d..9cf2ac995f 100644 --- a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java +++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java @@ -18,15 +18,23 @@ */ package org.apache.xml.security.stax.ext; -import org.apache.xml.security.stax.securityToken.SecurityTokenConstants; - import java.security.Key; import java.security.cert.X509Certificate; import java.security.spec.AlgorithmParameterSpec; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.xml.namespace.QName; +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.securityToken.SecurityTokenConstants; + +import static java.util.Objects.requireNonNull; /** * Main configuration class to supply keys etc. @@ -47,7 +55,7 @@ public class XMLSecurityProperties { private String encryptionKeyTransportDigestAlgorithm; private String encryptionKeyTransportMGFAlgorithm; private byte[] encryptionKeyTransportOAEPParams; - private final List encryptionParts = new LinkedList<>(); + private final List securePartSelectors = new ArrayList<>(); private Key encryptionKey; private Key encryptionTransportKey; private SecurityTokenConstants.KeyIdentifier encryptionKeyIdentifier; @@ -55,7 +63,6 @@ public class XMLSecurityProperties { private Key decryptionKey; - private final List signatureParts = new LinkedList<>(); private String signatureAlgorithm; private String signatureDigestAlgorithm; private String signatureCanonicalizationAlgorithm; @@ -95,12 +102,11 @@ protected XMLSecurityProperties(XMLSecurityProperties xmlSecurityProperties) { this.encryptionKeyTransportDigestAlgorithm = xmlSecurityProperties.encryptionKeyTransportDigestAlgorithm; this.encryptionKeyTransportMGFAlgorithm = xmlSecurityProperties.encryptionKeyTransportMGFAlgorithm; this.encryptionKeyTransportOAEPParams = xmlSecurityProperties.encryptionKeyTransportOAEPParams; - this.encryptionParts.addAll(xmlSecurityProperties.encryptionParts); + this.securePartSelectors.addAll(xmlSecurityProperties.securePartSelectors); this.encryptionKey = xmlSecurityProperties.encryptionKey; this.encryptionTransportKey = xmlSecurityProperties.encryptionTransportKey; this.encryptionKeyIdentifier = xmlSecurityProperties.encryptionKeyIdentifier; this.decryptionKey = xmlSecurityProperties.decryptionKey; - this.signatureParts.addAll(xmlSecurityProperties.signatureParts); this.signatureAlgorithm = xmlSecurityProperties.signatureAlgorithm; this.signatureDigestAlgorithm = xmlSecurityProperties.signatureDigestAlgorithm; this.signatureCanonicalizationAlgorithm = xmlSecurityProperties.signatureCanonicalizationAlgorithm; @@ -250,12 +256,20 @@ public Key getEncryptionKey() { } /** - * Adds a part which must be encrypted by the framework + * Adds a part which must be encrypted by the framework. + * Consider using {@link #addSecurePartSelector()} instead. * * @param securePart */ + @SuppressWarnings("PMD.AccessorClassGeneration") public void addEncryptionPart(SecurePart securePart) { - encryptionParts.add(securePart); + SecurePartElementSelector securePartElementSelector = new SecurePartElementSelector(securePart); + addSecurePartSelector() + .forAction(XMLSecurityConstants.ENCRYPTION) + .selectElement(securePartElementSelector) + .securePartWith(securePartElementSelector) + .requireNumOccurrences(securePart.isRequired() ? 1 : -1) + .build(); } /** @@ -263,8 +277,62 @@ public void addEncryptionPart(SecurePart securePart) { * * @return A List of SecurePart's */ - public List getEncryptionSecureParts() { - return encryptionParts; + public List getEncryptionPartSelectors() { + return getSecurePartSelectorsFor(XMLSecurityConstants.ENCRYPTION); + } + + private List getSecurePartSelectorsFor(XMLSecurityConstants.Action action) { + return securePartSelectors + .stream() + .filter(securePartSelector -> securePartSelector.getActions().contains(action)) + .collect(Collectors.toList()); + } + + private class SecurePartElementSelector implements ElementSelector, SecurePartFactory { + + private final SecurePart securePart; + private final ElementSelector elementSelector; + private boolean selected; + + private SecurePartElementSelector(SecurePart securePart) { + requireNonNull(securePart, "secure part is null"); + this.securePart = securePart; + ElementSelector elementSelector; + if (securePart.getExternalReference() != null) { + elementSelector = DocumentElementSelector.getInstance(); + } else if (securePart.getIdToSecure() != null) { + elementSelector = new ByAttributeElementSelector(() -> getIdAttributeNS(), securePart.getIdToSecure()); + } else if (securePart.getName() != null) { + elementSelector = new ByNameElementSelector(securePart.getName()); + } else if (securePart.isSecureEntireRequest()) { + elementSelector = element -> { + boolean selected = RootElementSelector.getInstance().select(element); + if (selected) { + // Preserve legacy behavior for backward compatibility. + securePart.setName(element.getName()); + } + return selected; + }; + } else { + elementSelector = NoElementSelector.getInstance(); + } + this.elementSelector = elementSelector; + } + + @Override + public boolean select(XMLSecStartElement element) { + return selected = elementSelector.select(element); + } + + @Override + public SecurePart createSecurePart(XMLSecStartElement element) { + return selected ? securePart : null; + } + + @Override + public String toString() { + return String.valueOf(securePart); + } } /** @@ -344,12 +412,25 @@ public void setSignatureCerts(X509Certificate[] signatureCerts) { this.signatureCerts = signatureCerts; } + /** + * Adds a part to be signed by the framework. + * Consider using {@link #addSecurePartSelector()} instead. + * + * @see #addSecurePartSelector() + */ + @SuppressWarnings("PMD.AccessorClassGeneration") public void addSignaturePart(SecurePart securePart) { - signatureParts.add(securePart); + SecurePartElementSelector securePartElementSelector = new SecurePartElementSelector(securePart); + addSecurePartSelector() + .forAction(XMLSecurityConstants.SIGNATURE) + .selectElement(securePartElementSelector) + .securePartWith(securePartElementSelector) + .requireNumOccurrences(securePart.isRequired() ? 1 : -1) + .build(); } - public List getSignatureSecureParts() { - return signatureParts; + public List getSignaturePartSelectors() { + return getSecurePartSelectorsFor(XMLSecurityConstants.SIGNATURE); } public String getSignatureAlgorithm() { @@ -539,4 +620,170 @@ public AlgorithmParameterSpec getAlgorithmParameterSpec() { public void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec) { this.algorithmParameterSpec = algorithmParameterSpec; } + + /** + * Adds a part to be secured by the framework using an element selector, secure part factory and required number + * of occurrences defined on the builder. + * The element selector defines which elements to encrypt. + * The secure part factory defines how to sign the elements. + * The required number of occurrences defines how many elements must be signed, and is verified after having + * processed the entire document. + * Processing will fail when the number of occurrences mismatches the required number. + * Use {@code -1} to disable verification. + * Use {@code 0} to verify that a secure part never occurs. + * + * @see SecurePartSelectorBuilder#selectElement(ElementSelector) + * @see SecurePartSelectorBuilder#securePartWith(SecurePartFactory) + * @see SecurePartSelectorBuilder#requireNumOccurrences(int) + */ + @SuppressWarnings("PMD.AccessorClassGeneration") + public SecurePartSelectorBuilder addSecurePartSelector() { + return new SecurePartSelectorBuilder(); + } + + /** + * A builder for secure part selectors which will be added to the security properties upon {@link #build()}. + * Use {@link #addSecurePartSelector()} to start building a signature part selector. + * @see #addSecurePartSelector() + */ + public class SecurePartSelectorBuilder { + + private List actions; + private ElementSelector elementSelector; + private SecurePartFactory securePartFactory; + private int requiredNumOccurrences = -1; + + private SecurePartSelectorBuilder() { + } + + /** + * Sets the actions to build a secure part selector for. + * The default is {@code null}, which means that the secure part selector will apply to all the actions + * defined on the security properties itself. + * + * @param actions The actions to build a secure part selector for, which may be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder forActions(List actions) { + this.actions = actions; + return this; + } + + /** + * Adds an action to build a secure part selector for. + * + * @param action The action to build a secure part selector for, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder forAction(XMLSecurityConstants.Action action) { + requireNonNull(action, "action is null"); + if (this.actions == null) { + this.actions = new ArrayList<>(2); + } + this.actions.add(action); + return this; + } + + /** + * Selects the elements to secure based on the given element selector. + * + * @param elementSelector An element selector, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder selectElement(ElementSelector elementSelector) { + requireNonNull(elementSelector, "element selector is null"); + this.elementSelector = elementSelector; + return this; + } + + /** + * Selects the root element to secure. + * This is equivalent to {@link SecurePart#setSecureEntireRequest(boolean)}. + * + * @return This builder. + */ + public SecurePartSelectorBuilder selectRootElement() { + return selectElement(RootElementSelector.getInstance()); + } + + /** + * Selects (an) element(s) to secure by name. + * + * @param name The name to select an element to secure by, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder selectElementByName(QName name) { + return selectElement(new ByNameElementSelector(name)); + } + + /** + * Selects the element(s) to secure by value of a given attribute name. + * When the given attribute name is {@code null}, {@link #getIdAttributeNS()} will be used. + * + * @param name The name of the attribute, which may be {@code null}. + * @param value The value of the attribute, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder selectElementByAttributeValue(QName name, String value) { + return selectElement(new ByAttributeElementSelector(() -> name != null ? name : getIdAttributeNS(), value)); + } + + /** + * Selects the element(s) to secure by value of the attribute name given by {@link #getIdAttributeNS()}. + * + * @param value The attribute value to select an element by, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder selectElementByAttributeValue(String value) { + return selectElementByAttributeValue(null, value); + } + + /** + * Secures an element with the parameters given by the secure part created with the factory upon selection. + * + * @param securePartFactory The factory to create a secure part with upon selection, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder securePartWith(SecurePartFactory securePartFactory) { + requireNonNull(securePartFactory, "secure part factory is null"); + this.securePartFactory = securePartFactory; + return this; + } + + /** + * Secures an element with the given modifier upon selection. + * + * @param modifier The modifier to secure an element with upon selection, which must not be {@code null}. + * @return This builder. + */ + public SecurePartSelectorBuilder securePartWithModifier(SecurePart.Modifier modifier) { + requireNonNull(modifier, "modifier is null"); + return securePartWith((element) -> element != null ? new SecurePart(element.getName(), modifier) : null); + } + + /** + * Requires a given number of occurrences, which will be verified after processing. + * The default is {@code -1}, which means verification is disabled. + * Use {@code 0} to verify that a secure part never occurs. + * + * @param requiredNumOccurrences A required number of occurrences, or {@code -1} for no such requirement. + * @return This builder. + */ + public SecurePartSelectorBuilder requireNumOccurrences(int requiredNumOccurrences) { + this.requiredNumOccurrences = requiredNumOccurrences; + return this; + } + + /** + * Builds a secure part selector and adds it to the security properties. + * + * @return A secure part selector, never {@code null}. + */ + public SecurePartSelector build() { + Supplier> actionsSupplier = () -> actions != null ? actions : XMLSecurityProperties.this.actions; + SecurePartSelector securePartSelector = new SecurePartSelector(actionsSupplier, elementSelector, securePartFactory, requiredNumOccurrences); + XMLSecurityProperties.this.securePartSelectors.add(securePartSelector); + return securePartSelector; + } + } } diff --git a/src/main/java/org/apache/xml/security/stax/impl/AbstractSecurityContextImpl.java b/src/main/java/org/apache/xml/security/stax/impl/AbstractSecurityContextImpl.java index 1b58164218..bde9fc1a66 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/AbstractSecurityContextImpl.java +++ b/src/main/java/org/apache/xml/security/stax/impl/AbstractSecurityContextImpl.java @@ -19,6 +19,7 @@ package org.apache.xml.security.stax.impl; import org.apache.xml.security.exceptions.XMLSecurityException; +import org.apache.xml.security.stax.ext.XMLSecurityProperties; import org.apache.xml.security.stax.securityEvent.SecurityEvent; import org.apache.xml.security.stax.securityEvent.SecurityEventListener; @@ -30,6 +31,15 @@ public class AbstractSecurityContextImpl { @SuppressWarnings("unchecked") private final Map content = Collections.synchronizedMap(new HashMap()); private final List securityEventListeners = new ArrayList<>(2); + private final XMLSecurityProperties securityProperties; + + public AbstractSecurityContextImpl(XMLSecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + + public XMLSecurityProperties getSecurityProperties() { + return securityProperties; + } public void addSecurityEventListener(SecurityEventListener securityEventListener) { if (securityEventListener != null) { @@ -75,34 +85,4 @@ public void putList(Object key, T value) { } entry.addAll(value); } - - @SuppressWarnings("unchecked") - public void putAsList(Object key, T value) { - List entry = (List) content.get(key); - if (entry == null) { - entry = new ArrayList<>(); - content.put(key, entry); - } - entry.add(value); - } - - @SuppressWarnings("unchecked") - public List getAsList(Object key) { - return (List) content.get(key); - } - - @SuppressWarnings("unchecked") - public void putAsMap(Object key, T mapKey, U mapValue) { - Map entry = (Map) content.get(key); - if (entry == null) { - entry = new HashMap<>(); - content.put(key, entry); - } - entry.put(mapKey, mapValue); - } - - @SuppressWarnings("unchecked") - public Map getAsMap(Object key) { - return (Map) content.get(key); - } } diff --git a/src/main/java/org/apache/xml/security/stax/impl/EncryptionPartDef.java b/src/main/java/org/apache/xml/security/stax/impl/EncryptionPartDef.java index d23cb94992..455e68ac72 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/EncryptionPartDef.java +++ b/src/main/java/org/apache/xml/security/stax/impl/EncryptionPartDef.java @@ -19,6 +19,7 @@ package org.apache.xml.security.stax.impl; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; import java.security.Key; @@ -28,6 +29,7 @@ */ public class EncryptionPartDef { + private SecurePartSelector securePartSelector; private SecurePart securePart; private SecurePart.Modifier modifier; private Key symmetricKey; @@ -36,6 +38,14 @@ public class EncryptionPartDef { private String cipherReferenceId; private String mimeType; + public SecurePartSelector getSecurePartSelector() { + return securePartSelector; + } + + public void setSecurePartSelector(SecurePartSelector securePartSelector) { + this.securePartSelector = securePartSelector; + } + public SecurePart getSecurePart() { return securePart; } diff --git a/src/main/java/org/apache/xml/security/stax/impl/InboundSecurityContextImpl.java b/src/main/java/org/apache/xml/security/stax/impl/InboundSecurityContextImpl.java index 40c8711507..fa082d7bc3 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/InboundSecurityContextImpl.java +++ b/src/main/java/org/apache/xml/security/stax/impl/InboundSecurityContextImpl.java @@ -21,6 +21,7 @@ import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.config.ConfigurationProperties; import org.apache.xml.security.stax.ext.InboundSecurityContext; +import org.apache.xml.security.stax.ext.XMLSecurityProperties; import org.apache.xml.security.stax.securityToken.InboundSecurityToken; import org.apache.xml.security.stax.securityToken.SecurityTokenProvider; import org.apache.xml.security.stax.securityEvent.AlgorithmSuiteSecurityEvent; @@ -39,6 +40,10 @@ public class InboundSecurityContextImpl extends AbstractSecurityContextImpl impl private final Map> securityTokenProviders = new HashMap<>(); + public InboundSecurityContextImpl(XMLSecurityProperties securityProperties) { + super(securityProperties); + } + @Override protected void forwardSecurityEvent(SecurityEvent securityEvent) throws XMLSecurityException { if (!InboundSecurityContextImpl.allowMD5Algorithm && SecurityEventConstants.AlgorithmSuite.equals(securityEvent.getSecurityEventType())) { diff --git a/src/main/java/org/apache/xml/security/stax/impl/OutboundSecurityContextImpl.java b/src/main/java/org/apache/xml/security/stax/impl/OutboundSecurityContextImpl.java index e87cde87d4..db34a91d0c 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/OutboundSecurityContextImpl.java +++ b/src/main/java/org/apache/xml/security/stax/impl/OutboundSecurityContextImpl.java @@ -19,6 +19,7 @@ package org.apache.xml.security.stax.impl; import org.apache.xml.security.stax.ext.OutboundSecurityContext; +import org.apache.xml.security.stax.ext.XMLSecurityProperties; import org.apache.xml.security.stax.securityToken.SecurityTokenProvider; import org.apache.xml.security.stax.securityToken.OutboundSecurityToken; @@ -36,6 +37,10 @@ public class OutboundSecurityContextImpl extends AbstractSecurityContextImpl imp private final Map> securityTokenProviders = new HashMap<>(); + public OutboundSecurityContextImpl(XMLSecurityProperties securityProperties) { + super(securityProperties); + } + @Override public void registerSecurityTokenProvider(String id, SecurityTokenProvider securityTokenProvider) { if (id == null) { diff --git a/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java b/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java index c89089bc6f..f4d0594e23 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java +++ b/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java @@ -19,6 +19,7 @@ package org.apache.xml.security.stax.impl; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; /** * SignaturePartDef holds information about parts to be signed @@ -26,6 +27,7 @@ */ public class SignaturePartDef { + private SecurePartSelector securePartSelector; private SecurePart securePart; private String sigRefId; private String digestValue; @@ -36,6 +38,14 @@ public class SignaturePartDef { private boolean externalResource; private boolean generateXPointer; + public SecurePartSelector getSecurePartSelector() { + return securePartSelector; + } + + public void setSecurePartSelector(SecurePartSelector elementSelector) { + this.securePartSelector = elementSelector; + } + public SecurePart getSecurePart() { return securePart; } diff --git a/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamWriter.java b/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamWriter.java index bd0fda2218..b7a1672aee 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamWriter.java +++ b/src/main/java/org/apache/xml/security/stax/impl/XMLSecurityStreamWriter.java @@ -20,8 +20,6 @@ import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.ext.OutputProcessorChain; -import org.apache.xml.security.stax.ext.SecurePart; -import org.apache.xml.security.stax.ext.XMLSecurityConstants; import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; import org.apache.xml.security.stax.ext.stax.XMLSecEvent; import org.apache.xml.security.stax.ext.stax.XMLSecEventFactory; @@ -49,8 +47,6 @@ public class XMLSecurityStreamWriter implements XMLStreamWriter { private NSContext namespaceContext = new NSContext(null); private boolean endDocumentWritten = false; private boolean haveToWriteEndElement = false; - private SecurePart signEntireRequestPart; - private SecurePart encryptEntireRequestPart; public XMLSecurityStreamWriter(OutputProcessorChain outputProcessorChain) { this.outputProcessorChain = outputProcessorChain; @@ -118,22 +114,6 @@ public void writeStartElement(String prefix, String localName, String namespaceU Element element; if (elementStack == null) { element = new Element(elementStack, namespaceContext, namespaceURI, localName, prefix); - if (signEntireRequestPart != null) { - signEntireRequestPart.setName(new QName(namespaceURI, localName, prefix)); - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.SIGNATURE_PARTS, - signEntireRequestPart.getName(), - signEntireRequestPart - ); - } - if (encryptEntireRequestPart != null) { - encryptEntireRequestPart.setName(new QName(namespaceURI, localName, prefix)); - outputProcessorChain.getSecurityContext().putAsMap( - XMLSecurityConstants.ENCRYPTION_PARTS, - encryptEntireRequestPart.getName(), - encryptEntireRequestPart - ); - } } else { element = new Element(elementStack, namespaceURI, localName, prefix); } @@ -165,7 +145,6 @@ public void writeEndElement() throws XMLStreamException { Element element = this.elementStack; this.elementStack = this.elementStack.getParentElement(); chainProcessEvent(XMLSecEventFactory.createXmlSecEndElement(element.getQName())); - } @Override @@ -353,22 +332,6 @@ public Object getProperty(String name) throws IllegalArgumentException { throw new IllegalArgumentException("Properties not supported"); } - public SecurePart getSignEntireRequestPart() { - return signEntireRequestPart; - } - - public void setSignEntireRequestPart(SecurePart signEntireRequestPart) { - this.signEntireRequestPart = signEntireRequestPart; - } - - public SecurePart getEncryptEntireRequestPart() { - return encryptEntireRequestPart; - } - - public void setEncryptEntireRequestPart(SecurePart encryptEntireRequestPart) { - this.encryptEntireRequestPart = encryptEntireRequestPart; - } - private static class Element { private Element parentElement; diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureReferenceVerifyInputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureReferenceVerifyInputProcessor.java index e9a7a0e2cf..55b564bc05 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureReferenceVerifyInputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureReferenceVerifyInputProcessor.java @@ -61,9 +61,9 @@ import org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_OmitCommentsTransformer; import org.apache.xml.security.stax.impl.util.DigestOutputStream; import org.apache.xml.security.stax.impl.util.IDGenerator; -import org.apache.xml.security.stax.impl.util.KeyValue; import org.apache.xml.security.stax.securityEvent.AlgorithmSuiteSecurityEvent; import org.apache.xml.security.stax.securityToken.InboundSecurityToken; +import org.apache.xml.security.utils.KeyValue; import org.apache.xml.security.utils.UnsyncBufferedOutputStream; import org.apache.xml.security.utils.XMLUtils; import org.slf4j.Logger; diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractEncryptOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractEncryptOutputProcessor.java index ad822a60c2..a01899f221 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractEncryptOutputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractEncryptOutputProcessor.java @@ -29,7 +29,6 @@ import java.util.Deque; import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; @@ -47,6 +46,7 @@ import org.apache.xml.security.stax.ext.AbstractOutputProcessor; import org.apache.xml.security.stax.ext.OutputProcessorChain; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; import org.apache.xml.security.stax.ext.XMLSecurityConstants; import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; import org.apache.xml.security.stax.ext.stax.XMLSecCharacters; @@ -74,14 +74,15 @@ public abstract class AbstractEncryptOutputProcessor extends AbstractOutputProce } private AbstractInternalEncryptionOutputProcessor activeInternalEncryptionOutputProcessor; + private final List encryptionPartDefList = new ArrayList<>(); public AbstractEncryptOutputProcessor() throws XMLSecurityException { super(); } - @Override - public abstract void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) - throws XMLStreamException, XMLSecurityException; + public List getEncryptionPartDefList() { + return encryptionPartDefList; + } @Override public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException { @@ -94,26 +95,27 @@ protected void doFinalInternal(OutputProcessorChain outputProcessorChain) throws } protected void verifyEncryptionParts(OutputProcessorChain outputProcessorChain) throws XMLSecurityException { - List encryptionPartDefs = - outputProcessorChain.getSecurityContext().getAsList(EncryptionPartDef.class); - - Map dynamicSecureParts = outputProcessorChain.getSecurityContext().getAsMap(XMLSecurityConstants.ENCRYPTION_PARTS); - Iterator> securePartsMapIterator = dynamicSecureParts.entrySet().iterator(); - loop: - while (securePartsMapIterator.hasNext()) { - Map.Entry securePartEntry = securePartsMapIterator.next(); - final SecurePart securePart = securePartEntry.getValue(); - - if (securePart.isRequired()) { - for (int i = 0; encryptionPartDefs != null && i < encryptionPartDefs.size(); i++) { - EncryptionPartDef encryptionPartDef = encryptionPartDefs.get(i); - - if (encryptionPartDef.getSecurePart() == securePart) { - continue loop; + List encryptionPartDefs = getEncryptionPartDefList(); + List encryptionPartSelectors = outputProcessorChain.getSecurityContext().get(XMLSecurityConstants.ENCRYPTION_PART_SELECTORS); + if (encryptionPartSelectors != null) { + loop: + for (SecurePartSelector encryptionPartSelector : encryptionPartSelectors) { + int requiredNumOccurrences = encryptionPartSelector.getRequiredNumOccurrences(); + if (requiredNumOccurrences >= 0) { + int numOccurrences = 0; + for (EncryptionPartDef encryptionPartDef : encryptionPartDefs) { + if (encryptionPartDef.getSecurePartSelector().equals(encryptionPartSelector)) { + numOccurrences++; + } + } + if (numOccurrences < requiredNumOccurrences) { + throw new XMLSecurityException("stax.encryption.tooFewOccurrences", + new Object[]{numOccurrences, requiredNumOccurrences, encryptionPartSelector}); + } else if (numOccurrences > requiredNumOccurrences) { + throw new XMLSecurityException("stax.encryption.tooManyOccurrences", + new Object[]{numOccurrences, requiredNumOccurrences, encryptionPartSelector}); } } - throw new XMLSecurityException("stax.encryption.securePartNotFound", - new Object[] {securePart.getName()}); } } } diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java index fe2e657699..0f0bae15a8 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java @@ -41,6 +41,7 @@ import org.apache.xml.security.stax.ext.OutputProcessorChain; import org.apache.xml.security.stax.ext.ResourceResolver; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; import org.apache.xml.security.stax.ext.Transformer; import org.apache.xml.security.stax.ext.XMLSecurityConstants; import org.apache.xml.security.stax.ext.XMLSecurityUtils; @@ -52,7 +53,6 @@ import org.apache.xml.security.stax.impl.util.DigestOutputStream; import org.apache.xml.security.utils.UnsyncBufferedOutputStream; import org.apache.xml.security.utils.XMLUtils; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,10 +73,6 @@ public List getSignaturePartDefList() { return signaturePartDefList; } - @Override - public abstract void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) - throws XMLStreamException, XMLSecurityException; - @Override public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException { doFinalInternal(outputProcessorChain); @@ -84,26 +80,22 @@ public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamE } protected void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLSecurityException, XMLStreamException { - Map dynamicSecureParts = - outputProcessorChain.getSecurityContext().getAsMap(XMLSecurityConstants.SIGNATURE_PARTS); - if (dynamicSecureParts != null) { - Iterator> securePartsMapIterator = dynamicSecureParts.entrySet().iterator(); - while (securePartsMapIterator.hasNext()) { - Map.Entry securePartEntry = securePartsMapIterator.next(); - final SecurePart securePart = securePartEntry.getValue(); - if (securePart.getExternalReference() != null) { - digestExternalReference(outputProcessorChain, securePart); - } - } + List securePartSelectors = getSecurityProperties().getSignaturePartSelectors(); + for (SecurePartSelector securePartSelector : securePartSelectors) { + digestExternalReference(outputProcessorChain, securePartSelector); } verifySignatureParts(outputProcessorChain); } protected void digestExternalReference( - OutputProcessorChain outputProcessorChain, SecurePart securePart) + OutputProcessorChain outputProcessorChain, SecurePartSelector securePartSelector) throws XMLSecurityException, XMLStreamException { + final SecurePart securePart = securePartSelector.select(null); + if (securePart == null || securePart.getExternalReference() == null) { + return; + } final String externalReference = securePart.getExternalReference(); ResourceResolver resourceResolver = ResourceResolverMapper.getResourceResolver( @@ -118,6 +110,7 @@ protected void digestExternalReference( InputStream inputStream = resourceResolver.getInputStreamFromExternalReference(); SignaturePartDef signaturePartDef = new SignaturePartDef(); + signaturePartDef.setSecurePartSelector(securePartSelector); signaturePartDef.setSecurePart(securePart); signaturePartDef.setSigRefId(externalReference); signaturePartDef.setExternalResource(true); @@ -149,24 +142,25 @@ protected void digestExternalReference( protected void verifySignatureParts(OutputProcessorChain outputProcessorChain) throws XMLSecurityException { List signaturePartDefs = getSignaturePartDefList(); - Map dynamicSecureParts = outputProcessorChain.getSecurityContext().getAsMap(XMLSecurityConstants.SIGNATURE_PARTS); - if (dynamicSecureParts != null) { - Iterator> securePartsMapIterator = dynamicSecureParts.entrySet().iterator(); + List signaturePartSelectors = outputProcessorChain.getSecurityContext().get(XMLSecurityConstants.SIGNATURE_PART_SELECTORS); + if (signaturePartSelectors != null) { loop: - while (securePartsMapIterator.hasNext()) { - Map.Entry securePartEntry = securePartsMapIterator.next(); - final SecurePart securePart = securePartEntry.getValue(); - - if (securePart.isRequired()) { - for (int i = 0; i < signaturePartDefs.size(); i++) { - SignaturePartDef signaturePartDef = signaturePartDefs.get(i); - - if (signaturePartDef.getSecurePart() == securePart) { - continue loop; + for (SecurePartSelector signaturePartSelector : signaturePartSelectors) { + int requiredNumOccurrences = signaturePartSelector.getRequiredNumOccurrences(); + if (requiredNumOccurrences >= 0) { + int numOccurrences = 0; + for (SignaturePartDef signaturePartDef : signaturePartDefs) { + if (signaturePartDef.getSecurePartSelector().equals(signaturePartSelector)) { + numOccurrences++; } } - throw new XMLSecurityException("stax.signature.securePartNotFound", - new Object[] {securePart.getName()}); + if (numOccurrences < requiredNumOccurrences) { + throw new XMLSecurityException("stax.signature.tooFewOccurrences", + new Object[]{numOccurrences, requiredNumOccurrences, signaturePartSelector}); + } else if (numOccurrences > requiredNumOccurrences) { + throw new XMLSecurityException("stax.signature.tooManyOccurrences", + new Object[]{numOccurrences, requiredNumOccurrences, signaturePartSelector}); + } } } } diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLEncryptOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLEncryptOutputProcessor.java index 1264d24df4..3231d37a42 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLEncryptOutputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLEncryptOutputProcessor.java @@ -41,6 +41,7 @@ import org.apache.xml.security.stax.config.JCEAlgorithmMapper; import org.apache.xml.security.stax.ext.OutputProcessorChain; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; import org.apache.xml.security.stax.ext.XMLSecurityConstants; import org.apache.xml.security.stax.ext.XMLSecurityUtils; import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; @@ -51,6 +52,7 @@ import org.apache.xml.security.stax.securityToken.OutboundSecurityToken; import org.apache.xml.security.stax.securityToken.SecurityTokenConstants; import org.apache.xml.security.stax.securityToken.SecurityTokenProvider; +import org.apache.xml.security.utils.KeyValue; import org.apache.xml.security.utils.XMLUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,8 +76,10 @@ public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputPro //avoid double encryption when child elements matches too if (getActiveInternalEncryptionOutputProcessor() == null) { - SecurePart securePart = securePartMatches(xmlSecStartElement, outputProcessorChain, XMLSecurityConstants.ENCRYPTION_PARTS); - if (securePart != null) { + KeyValue match = securePartMatches(xmlSecStartElement, outputProcessorChain, XMLSecurityConstants.ENCRYPTION_PART_SELECTORS); + if (match != null) { + SecurePartSelector securePartSelector = match.getKey(); + SecurePart securePart = match.getValue(); LOG.debug("Matched encryptionPart for encryption"); String tokenId = outputProcessorChain.getSecurityContext().get( XMLSecurityConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION); @@ -84,12 +88,13 @@ public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputPro final OutboundSecurityToken securityToken = securityTokenProvider.getSecurityToken(); EncryptionPartDef encryptionPartDef = new EncryptionPartDef(); + encryptionPartDef.setSecurePartSelector(securePartSelector); encryptionPartDef.setSecurePart(securePart); encryptionPartDef.setModifier(securePart.getModifier()); encryptionPartDef.setEncRefId(IDGenerator.generateID(null)); encryptionPartDef.setKeyId(securityTokenProvider.getId()); encryptionPartDef.setSymmetricKey(securityToken.getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm())); - outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef); + getEncryptionPartDefList().add(encryptionPartDef); AbstractInternalEncryptionOutputProcessor internalEncryptionOutputProcessor = createInternalEncryptionOutputProcessor( diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java index e98d3b76d0..3c3871ed15 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java +++ b/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java @@ -25,6 +25,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.Attribute; +import org.apache.xml.security.stax.ext.SecurePartSelector; +import org.apache.xml.security.utils.KeyValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.xml.security.exceptions.XMLSecurityException; @@ -64,13 +66,16 @@ public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputPro //avoid double signature when child elements matches too if (getActiveInternalSignatureOutputProcessor() == null) { - SecurePart securePart = securePartMatches(xmlSecStartElement, outputProcessorChain, XMLSecurityConstants.SIGNATURE_PARTS); - if (securePart != null) { + KeyValue match = securePartMatches(xmlSecStartElement, outputProcessorChain, XMLSecurityConstants.SIGNATURE_PART_SELECTORS); + if (match != null) { + SecurePartSelector securePartSelector = match.getKey(); + SecurePart securePart = match.getValue(); LOG.debug("Matched securePart for signature"); InternalSignatureOutputProcessor internalSignatureOutputProcessor = null; SignaturePartDef signaturePartDef = new SignaturePartDef(); + signaturePartDef.setSecurePartSelector(securePartSelector); signaturePartDef.setSecurePart(securePart); signaturePartDef.setTransforms(securePart.getTransforms()); if (signaturePartDef.getTransforms() == null) { diff --git a/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecEventBaseImpl.java b/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecEventBaseImpl.java index 4763c58f17..5e782f8c27 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecEventBaseImpl.java +++ b/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecEventBaseImpl.java @@ -37,7 +37,7 @@ public abstract class XMLSecEventBaseImpl implements XMLSecEvent { private static final EmptyIterator EMPTY_ITERATOR = new EmptyIterator(); - protected XMLSecStartElement parentXMLSecStartELement; + protected XMLSecStartElement parentXMLSecStartElement; @SuppressWarnings("unchecked") protected static EmptyIterator getEmptyIterator() { @@ -46,26 +46,26 @@ protected static EmptyIterator getEmptyIterator() { @Override public void setParentXMLSecStartElement(XMLSecStartElement xmlSecStartElement) { - this.parentXMLSecStartELement = xmlSecStartElement; + this.parentXMLSecStartElement = xmlSecStartElement; } @Override public XMLSecStartElement getParentXMLSecStartElement() { - return parentXMLSecStartELement; + return parentXMLSecStartElement; } @Override public int getDocumentLevel() { - if (parentXMLSecStartELement != null) { - return parentXMLSecStartELement.getDocumentLevel(); + if (parentXMLSecStartElement != null) { + return parentXMLSecStartElement.getDocumentLevel(); } return 0; } @Override public void getElementPath(List list) { - if (parentXMLSecStartELement != null) { - parentXMLSecStartELement.getElementPath(list); + if (parentXMLSecStartElement != null) { + parentXMLSecStartElement.getElementPath(list); } } @@ -81,7 +81,7 @@ public XMLSecStartElement getStartElementAtLevel(int level) { if (getDocumentLevel() < level) { return null; } - return parentXMLSecStartELement.getStartElementAtLevel(level); + return parentXMLSecStartElement.getStartElementAtLevel(level); } @Override diff --git a/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecStartElementImpl.java b/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecStartElementImpl.java index 5d02871a99..b9cbf8d72b 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecStartElementImpl.java +++ b/src/main/java/org/apache/xml/security/stax/impl/stax/XMLSecStartElementImpl.java @@ -89,8 +89,8 @@ public Iterator getAttributes() { @Override public void getAttributesFromCurrentScope(List comparableAttributeList) { comparableAttributeList.addAll(attributes); - if (parentXMLSecStartELement != null) { - parentXMLSecStartELement.getAttributesFromCurrentScope(comparableAttributeList); + if (parentXMLSecStartElement != null) { + parentXMLSecStartElement.getAttributesFromCurrentScope(comparableAttributeList); } } @@ -126,7 +126,7 @@ public XMLSecStartElement getStartElementAtLevel(int level) { } else if (thisLevel == level) { return this; } else { - return parentXMLSecStartELement.getStartElementAtLevel(level); + return parentXMLSecStartElement.getStartElementAtLevel(level); } } @@ -142,8 +142,8 @@ public Iterator getNamespaces() { @Override public void getNamespacesFromCurrentScope(List comparableNamespaceList) { - if (parentXMLSecStartELement != null) { - parentXMLSecStartELement.getNamespacesFromCurrentScope(comparableNamespaceList); + if (parentXMLSecStartElement != null) { + parentXMLSecStartElement.getNamespacesFromCurrentScope(comparableNamespaceList); } comparableNamespaceList.addAll(namespaces); } @@ -183,8 +183,8 @@ public String getNamespaceURI(String prefix) { return comparableNamespace.getNamespaceURI(); } } - if (parentXMLSecStartELement != null) { - return parentXMLSecStartELement.getNamespaceURI(prefix); + if (parentXMLSecStartElement != null) { + return parentXMLSecStartElement.getNamespaceURI(prefix); } return null; } @@ -197,8 +197,8 @@ public String getPrefix(String namespaceURI) { return comparableNamespace.getPrefix(); } } - if (parentXMLSecStartELement != null) { - return parentXMLSecStartELement.getNamespaceContext().getPrefix(namespaceURI); + if (parentXMLSecStartElement != null) { + return parentXMLSecStartElement.getNamespaceContext().getPrefix(namespaceURI); } return null; } @@ -231,8 +231,8 @@ public String getNamespaceURI(String prefix) { return comparableNamespace.getNamespaceURI(); } } - if (parentXMLSecStartELement != null) { - return parentXMLSecStartELement.getNamespaceURI(prefix); + if (parentXMLSecStartElement != null) { + return parentXMLSecStartElement.getNamespaceURI(prefix); } return null; } diff --git a/src/main/java/org/apache/xml/security/stax/impl/util/KeyValue.java b/src/main/java/org/apache/xml/security/utils/KeyValue.java similarity index 92% rename from src/main/java/org/apache/xml/security/stax/impl/util/KeyValue.java rename to src/main/java/org/apache/xml/security/utils/KeyValue.java index efaa319d00..7077dbe81d 100644 --- a/src/main/java/org/apache/xml/security/stax/impl/util/KeyValue.java +++ b/src/main/java/org/apache/xml/security/utils/KeyValue.java @@ -16,14 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.xml.security.stax.impl.util; +package org.apache.xml.security.utils; /** */ public class KeyValue { - private E key; - private K value; + private final E key; + private final K value; public KeyValue(E key, K value) { this.key = key; diff --git a/src/test/java/org/apache/xml/security/stax/ext/ByAttributeElementSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/ByAttributeElementSelectorTest.java new file mode 100644 index 0000000000..4c2fc6d7b7 --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/ByAttributeElementSelectorTest.java @@ -0,0 +1,55 @@ +package org.apache.xml.security.stax.ext; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecAttributeImpl; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static java.util.Arrays.asList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ByAttributeElementSelectorTest { + + @Test + public void testConstructionThrowsWhenValueIsNull() { + assertThrows(NullPointerException.class, () -> new ByAttributeElementSelector(new QName("attr1"), null)); + } + + @Test + public void testSelection() { + QName attributeName = new QName("attr1"); + String value = "val1"; + ByAttributeElementSelector elementSelector = new ByAttributeElementSelector(attributeName, value); + assertThat(elementSelector.select(null), is(false)); + + QName elementName = new QName("element"); + List attributes1 = asList(new XMLSecAttributeImpl(attributeName, "val1")); + XMLSecStartElement element1 = new XMLSecStartElementImpl(elementName, attributes1, null); + assertThat(elementSelector.select(element1), is(true)); + + List attributes2 = asList(new XMLSecAttributeImpl(attributeName, "val2")); + XMLSecStartElement element2 = new XMLSecStartElementImpl(elementName, attributes2, null); + assertThat(elementSelector.select(element2), is(false)); + + QName attributeName2 = new QName("attr2"); + List attributes3 = asList(new XMLSecAttributeImpl(attributeName2, "val1")); + XMLSecStartElement element3 = new XMLSecStartElementImpl(elementName, attributes3, null); + assertThat(elementSelector.select(element3), is(false)); + } + + @Test + public void testStringValue() { + assertThat(new ByAttributeElementSelector(new QName("attr1"), "val1").toString(), is(equalTo("//*[@attr1='val1']"))); + assertThat(new ByAttributeElementSelector(new QName("urn:test:ns", "attr1"), "val1").toString(), is(equalTo("//*[@{urn:test:ns}attr1='val1']"))); + assertThat(new ByAttributeElementSelector(new QName(null, "attr1", "pf1"), "val1").toString(), is(equalTo("//*[@attr1='val1']"))); + assertThat(new ByAttributeElementSelector(new QName("urn:test:ns", "attr1", "pf1"), "val1").toString(), is(equalTo("//*[@{urn:test:ns}attr1='val1']"))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/ByNameElementSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/ByNameElementSelectorTest.java new file mode 100644 index 0000000000..ceb6fdd7ed --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/ByNameElementSelectorTest.java @@ -0,0 +1,39 @@ +package org.apache.xml.security.stax.ext; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ByNameElementSelectorTest { + + @Test + public void testConstructionThrowsWhenNameIsNull() { + assertThrows(NullPointerException.class, () -> new ByNameElementSelector(null)); + } + + @Test + public void testSelection() { + QName name = new QName("element"); + ByNameElementSelector elementSelector = new ByNameElementSelector(name); + assertThat(elementSelector.select(null), is(false)); + XMLSecStartElement element = new XMLSecStartElementImpl(name, null, null); + assertThat(elementSelector.select(element), is(true)); + XMLSecStartElement anotherElement = new XMLSecStartElementImpl(new QName("urn:test:ns", "element"), null, null); + assertThat(elementSelector.select(anotherElement), is(false)); + } + + @Test + public void testStringValue() { + assertThat(new ByNameElementSelector(new QName("element")).toString(), is(equalTo("//element"))); + assertThat(new ByNameElementSelector(new QName("urn:test:ns", "element")).toString(), is(equalTo("//{urn:test:ns}element"))); + assertThat(new ByNameElementSelector(new QName(null, "element", "pf")).toString(), is(equalTo("//element"))); + assertThat(new ByNameElementSelector(new QName("urn:test:ns0", "element", "pf0")).toString(), is(equalTo("//{urn:test:ns0}element"))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/DocumentElementSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/DocumentElementSelectorTest.java new file mode 100644 index 0000000000..2d0b1e6c2a --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/DocumentElementSelectorTest.java @@ -0,0 +1,27 @@ +package org.apache.xml.security.stax.ext; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +public class DocumentElementSelectorTest { + + @Test + public void testSelection() { + DocumentElementSelector elementSelector = DocumentElementSelector.getInstance(); + assertThat(elementSelector.select(null), is(true)); + XMLSecStartElement element = new XMLSecStartElementImpl(new QName("root"), null, null); + assertThat(elementSelector.select(element), is(false)); + } + + @Test + public void testStringValue() { + assertThat(DocumentElementSelector.getInstance().toString(), is(equalTo("/"))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/NoElementSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/NoElementSelectorTest.java new file mode 100644 index 0000000000..61dc445840 --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/NoElementSelectorTest.java @@ -0,0 +1,27 @@ +package org.apache.xml.security.stax.ext; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +public class NoElementSelectorTest { + + @Test + public void testSelection() { + NoElementSelector elementSelector = NoElementSelector.getInstance(); + assertThat(elementSelector.select(null), is(false)); + XMLSecStartElement element = new XMLSecStartElementImpl(new QName("element"), null, null); + assertThat(elementSelector.select(element), is(false)); + } + + @Test + public void testStringValue() { + assertThat(NoElementSelector.getInstance().toString(), is(equalTo(""))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/RootElementSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/RootElementSelectorTest.java new file mode 100644 index 0000000000..954ebdd2a6 --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/RootElementSelectorTest.java @@ -0,0 +1,33 @@ +package org.apache.xml.security.stax.ext; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class RootElementSelectorTest { + + @Test + public void testSelection() { + RootElementSelector elementSelector = RootElementSelector.getInstance(); + assertThat(elementSelector, is(notNullValue())); + assertThat(elementSelector.select(null), is(false)); + XMLSecStartElement rootElement = new XMLSecStartElementImpl(new QName("root"), null, null); + assertThat(elementSelector.select(rootElement), is(true)); + XMLSecStartElement branchElement = new XMLSecStartElementImpl(new QName("branch"), null, null, rootElement); + assertThat(elementSelector.select(branchElement), is(false)); + XMLSecStartElement anotherRootElement = new XMLSecStartElementImpl(new QName("anotherRoot"), null, null); + assertThat(elementSelector.select(anotherRootElement), is(true)); + } + + @Test + public void testStringValue() { + assertThat(RootElementSelector.getInstance().toString(), is(equalTo("/*"))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/SecurePartSelectorTest.java b/src/test/java/org/apache/xml/security/stax/ext/SecurePartSelectorTest.java new file mode 100644 index 0000000000..2935c10ead --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/SecurePartSelectorTest.java @@ -0,0 +1,113 @@ +package org.apache.xml.security.stax.ext; + +import java.util.Collections; +import java.util.UUID; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class SecurePartSelectorTest { + + @Test + public void testConstructionThrowsWhenActionsSupplierIsNull() { + assertThrows(NullPointerException.class, () -> new SecurePartSelector(null, mock(ElementSelector.class), mock(SecurePartFactory.class), -1)); + } + + @Test + public void testConstructionThrowsWhenElementSelectorIsNull() { + assertThrows(NullPointerException.class, () -> new SecurePartSelector(Collections::emptyList, null, mock(SecurePartFactory.class), -1)); + } + + @Test + public void testConstructionThrowsWhenSecurePartFactoryIsNull() { + assertThrows(NullPointerException.class, () -> new SecurePartSelector(Collections::emptyList, mock(ElementSelector.class), null, -1)); + } + + @Test + public void testSelectReturnsNullWhenNotSelected() throws Exception { + QName name = new QName("element"); + XMLSecStartElement element = new XMLSecStartElementImpl(name, null, null); + ElementSelector elementSelector = mock(ElementSelector.class); + when(elementSelector.select(element)).thenReturn(false); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + + SecurePartSelector securePartSelector = new SecurePartSelector(Collections::emptyList, elementSelector, securePartFactory, -1); + + assertThat(securePartSelector.select(element), is(nullValue())); + verify(securePartFactory, never()).createSecurePart(nullable(XMLSecStartElement.class)); + } + + @Test + public void testSelectDelegatesToFactory() throws Exception { + QName name = new QName("element"); + XMLSecStartElement element = new XMLSecStartElementImpl(name, null, null); + ElementSelector elementSelector = mock(ElementSelector.class); + when(elementSelector.select(element)).thenReturn(true); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + SecurePart securePart = new SecurePart(name, SecurePart.Modifier.Element); + when(securePartFactory.createSecurePart(element)).thenReturn(securePart); + + SecurePartSelector securePartSelector = new SecurePartSelector(Collections::emptyList, elementSelector, securePartFactory, -1); + + assertThat(securePartSelector.select(element), is(securePart)); + verify(securePartFactory).createSecurePart(element); + verifyNoMoreInteractions(securePartFactory); + } + + @Test + public void testToStringDelegatesToElementSelector() { + ElementSelector elementSelector = mock(ElementSelector.class); + String elementSelectorStringValue = UUID.randomUUID().toString(); + when(elementSelector.toString()).thenReturn(elementSelectorStringValue); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + + SecurePartSelector securePartSelector = new SecurePartSelector(Collections::emptyList, elementSelector, securePartFactory, -1); + + assertThat(securePartSelector.toString(), is(equalTo(elementSelectorStringValue))); + } + + @Test + public void testRequiredNumOccurrences() { + ElementSelector elementSelector = mock(ElementSelector.class); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + + SecurePartSelector securePartSelector = new SecurePartSelector(Collections::emptyList, elementSelector, securePartFactory, 2); + + assertThat(securePartSelector.getRequiredNumOccurrences(), is(2)); + } + + @Test + public void testActions() { + ElementSelector elementSelector = mock(ElementSelector.class); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + + SecurePartSelector securePartSelector = new SecurePartSelector(() -> Collections.singletonList(XMLSecurityConstants.ENCRYPTION), elementSelector, securePartFactory, -1); + + assertThat(securePartSelector.getActions(), is(equalTo(Collections.singletonList(XMLSecurityConstants.ENCRYPTION)))); + } + + @Test + public void testGetActionsThrowsWhenSuppliedActionsAreNull() { + ElementSelector elementSelector = mock(ElementSelector.class); + SecurePartFactory securePartFactory = mock(SecurePartFactory.class); + + SecurePartSelector securePartSelector = new SecurePartSelector(() -> null, elementSelector, securePartFactory, -1); + + assertThrows(NullPointerException.class, () -> securePartSelector.getActions()); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/ext/XMLSecurityPropertiesTest.java b/src/test/java/org/apache/xml/security/stax/ext/XMLSecurityPropertiesTest.java new file mode 100644 index 0000000000..6a05460017 --- /dev/null +++ b/src/test/java/org/apache/xml/security/stax/ext/XMLSecurityPropertiesTest.java @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.xml.security.stax.ext; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.SecurePart.Modifier; +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; + +public class XMLSecurityPropertiesTest { + + @Test + public void testDefaultValues() { + XMLSecurityProperties properties = new XMLSecurityProperties(); + assertThat(properties.getEncryptionPartSelectors(), is(empty())); + assertThat(properties.getSignaturePartSelectors(), is(empty())); + } + + @Test + public void testAddEncryptionPart() { + XMLSecurityProperties properties = new XMLSecurityProperties(); + QName name = new QName("tag"); + SecurePart encryptionPart = new SecurePart(name, Modifier.Element); + properties.addEncryptionPart(encryptionPart); + List selectors = properties.getEncryptionPartSelectors(); + assertThat(selectors, hasSize(1)); + SecurePartSelector selector = selectors.get(0); + XMLSecStartElement element = new XMLSecStartElementImpl(name, null, null); + assertThat(selector.select(element), is(sameInstance(encryptionPart))); + } + + @Test + public void testAddSignaturePart() { + XMLSecurityProperties properties = new XMLSecurityProperties(); + QName name = new QName("tag"); + SecurePart signaturePart = new SecurePart(name, Modifier.Element); + properties.addSignaturePart(signaturePart); + List selectors = properties.getSignaturePartSelectors(); + assertThat(selectors, hasSize(1)); + SecurePartSelector selector = selectors.get(0); + XMLSecStartElement element = new XMLSecStartElementImpl(name, null, null); + assertThat(selector.select(element), is(sameInstance(signaturePart))); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/stax/impl/securityToken/SecurityTokenFactoryImplTest.java b/src/test/java/org/apache/xml/security/stax/impl/securityToken/SecurityTokenFactoryImplTest.java index 20575df6ad..213a44e6a5 100644 --- a/src/test/java/org/apache/xml/security/stax/impl/securityToken/SecurityTokenFactoryImplTest.java +++ b/src/test/java/org/apache/xml/security/stax/impl/securityToken/SecurityTokenFactoryImplTest.java @@ -61,7 +61,7 @@ public void setUp() throws Exception { xmlSecurityProperties = new XMLSecurityProperties(); - inboundSecurityContext = new InboundSecurityContextImpl(); + inboundSecurityContext = new InboundSecurityContextImpl(xmlSecurityProperties); } @@ -90,7 +90,7 @@ public void testKeyNameTokenWithSignatureVerificationKeySet() throws Exception { xmlSecurityProperties.addKeyNameMapping("mykey", loadPublicKey("dsa.key", "DSA")); xmlSecurityProperties.setSignatureVerificationKey(loadPublicKey("rsa.key", "RSA")); - InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(); + InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(xmlSecurityProperties); InboundSecurityToken token = factory.getSecurityToken(keyInfoType, keyUsage, xmlSecurityProperties, inboundSecurityContext); @@ -106,7 +106,7 @@ public void testKeyNameTokenWithoutKeyInMap() throws Exception { SecurityTokenConstants.KeyUsage keyUsage = SecurityTokenConstants.KeyUsage_Signature_Verification; - InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(); + InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(xmlSecurityProperties); XMLSecurityException exception = Assertions.assertThrows(XMLSecurityException.class, () -> { factory.getSecurityToken(keyInfoType, keyUsage, xmlSecurityProperties, inboundSecurityContext); @@ -126,7 +126,7 @@ public void testKeyNameTokenWithWrongKeyInMap() throws Exception { xmlSecurityProperties.addKeyNameMapping("mykey", privateKey); - InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(); + InboundSecurityContext inboundSecurityContext = new InboundSecurityContextImpl(xmlSecurityProperties); XMLSecurityException exception = Assertions.assertThrows(XMLSecurityException.class, () -> { factory.getSecurityToken(keyInfoType, keyUsage, xmlSecurityProperties, inboundSecurityContext); diff --git a/src/test/java/org/apache/xml/security/test/stax/InputProcessorChainTest.java b/src/test/java/org/apache/xml/security/test/stax/InputProcessorChainTest.java index 3dc4e65df0..2cf0cdf86e 100644 --- a/src/test/java/org/apache/xml/security/test/stax/InputProcessorChainTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/InputProcessorChainTest.java @@ -20,6 +20,7 @@ import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.config.Init; +import org.apache.xml.security.stax.ext.XMLSecurityProperties; import org.apache.xml.security.stax.impl.InboundSecurityContextImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -98,7 +99,7 @@ public void doFinal(InputProcessorChain inputProcessorChain) throws XMLStreamExc @Test public void testAddProcessorPhase1() { - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl()); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl(new XMLSecurityProperties())); AbstractInputProcessor inputProcessor1 = new AbstractInputProcessor() { }; @@ -119,7 +120,7 @@ public void testAddProcessorPhase1() { @Test public void testAddProcessorPhase2() { - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl()); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl(new XMLSecurityProperties())); AbstractInputProcessor inputProcessor1 = new AbstractInputProcessor() { }; @@ -159,7 +160,7 @@ public void testAddProcessorPhase2() { @Test public void testAddProcessorBefore1() { - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl()); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl(new XMLSecurityProperties())); AbstractInputProcessor inputProcessor1 = new AbstractInputProcessor() { }; @@ -202,7 +203,7 @@ public void testAddProcessorBefore1() { @Test public void testAddProcessorAfter1() { - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl()); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl(new XMLSecurityProperties())); AbstractInputProcessor inputProcessor1 = new AbstractInputProcessor() { }; @@ -245,7 +246,7 @@ public void testAddProcessorAfter1() { @Test public void testAddProcessorBeforeAndAfter1() { - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl()); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(new InboundSecurityContextImpl(new XMLSecurityProperties())); AbstractInputProcessor inputProcessor1 = new AbstractInputProcessor() { }; diff --git a/src/test/java/org/apache/xml/security/test/stax/OutputProcessorChainTest.java b/src/test/java/org/apache/xml/security/test/stax/OutputProcessorChainTest.java index d6d49c8557..f8bc7e317b 100644 --- a/src/test/java/org/apache/xml/security/test/stax/OutputProcessorChainTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/OutputProcessorChainTest.java @@ -106,7 +106,7 @@ public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamE @Test public void testAddProcessorPhase1() { - OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl()); + OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl(new XMLSecurityProperties())); AbstractOutputProcessor outputProcessor1 = new AbstractOutputProcessor() { }; @@ -127,7 +127,7 @@ public void testAddProcessorPhase1() { @Test public void testAddProcessorPhase2() { - OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl()); + OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl(new XMLSecurityProperties())); AbstractOutputProcessor outputProcessor1 = new AbstractOutputProcessor() { }; @@ -167,7 +167,7 @@ public void testAddProcessorPhase2() { @Test public void testAddProcessorBefore1() { - OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl()); + OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl(new XMLSecurityProperties())); AbstractOutputProcessor outputProcessor1 = new AbstractOutputProcessor() { }; @@ -210,7 +210,7 @@ public void testAddProcessorBefore1() { @Test public void testAddProcessorAfter1() { - OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl()); + OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl(new XMLSecurityProperties())); AbstractOutputProcessor outputProcessor1 = new AbstractOutputProcessor() { }; @@ -253,7 +253,7 @@ public void testAddProcessorAfter1() { @Test public void testAddProcessorBeforeAndAfter1() { - OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl()); + OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(new OutboundSecurityContextImpl(new XMLSecurityProperties())); AbstractOutputProcessor outputProcessor1 = new AbstractOutputProcessor() { }; diff --git a/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java b/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java index 87f1e2d511..7c8db54d4e 100644 --- a/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamReaderTest.java @@ -75,7 +75,7 @@ public void setUp() throws Exception { public void testPassThroughDocumentEvents() throws Exception { XMLSecurityProperties securityProperties = new XMLSecurityProperties(); securityProperties.setSkipDocumentEvents(false); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); inputProcessorChain.addProcessor(new EventReaderProcessor()); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); @@ -87,7 +87,7 @@ public void testPassThroughDocumentEvents() throws Exception { public void testSkipThroughDocumentEvents() throws Exception { XMLSecurityProperties securityProperties = new XMLSecurityProperties(); securityProperties.setSkipDocumentEvents(true); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); inputProcessorChain.addProcessor(new EventReaderProcessor()); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); @@ -98,7 +98,7 @@ public void testSkipThroughDocumentEvents() throws Exception { @Test public void testIdentityTransformSource() throws Exception { XMLSecurityProperties securityProperties = new XMLSecurityProperties(); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); inputProcessorChain.addProcessor(new EventReaderProcessor()); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); @@ -117,11 +117,11 @@ public void testDocumentDeclaration() throws Exception { ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1)); XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLStreamReader stdXmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlInput); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); - inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityProperties securityProperties = new XMLSecurityProperties(); securityProperties.setSkipDocumentEvents(false); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); + inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); advanceToFirstEvent(xmlSecurityStreamReader); assertThat(xmlSecurityStreamReader.getEventType(), is(XMLStreamConstants.START_DOCUMENT)); @@ -148,11 +148,11 @@ public void testDocumentDeclarationWithoutOptionalAttributes() throws Exception ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1)); XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLStreamReader stdXmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlInput); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); - inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityProperties securityProperties = new XMLSecurityProperties(); securityProperties.setSkipDocumentEvents(false); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); + inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); advanceToFirstEvent(xmlSecurityStreamReader); assertThat(xmlSecurityStreamReader.getEventType(), is(XMLStreamConstants.START_DOCUMENT)); @@ -169,11 +169,11 @@ public void testDocumentDeclarationWhenSkipDocumentEvents() throws Exception { ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1)); XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLStreamReader stdXmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlInput); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); - InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); - inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityProperties securityProperties = new XMLSecurityProperties(); securityProperties.setSkipDocumentEvents(true); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); + InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext); + inputProcessorChain.addProcessor(new EventReaderProcessor(stdXmlStreamReader)); XMLSecurityStreamReader xmlSecurityStreamReader = new XMLSecurityStreamReader(inputProcessorChain, securityProperties); advanceToFirstEvent(xmlSecurityStreamReader); assertThat(xmlSecurityStreamReader.getEventType(), is(XMLStreamConstants.START_ELEMENT)); @@ -198,7 +198,7 @@ private static void advanceToFirstEvent(XMLStreamReader xmlStreamReader) throws @Test public void testCorrectness() throws Exception { XMLSecurityProperties securityProperties = new XMLSecurityProperties(); - InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(); + InboundSecurityContextImpl securityContext = new InboundSecurityContextImpl(securityProperties); DocumentContextImpl documentContext = new DocumentContextImpl(); documentContext.setEncoding(StandardCharsets.UTF_8.name()); InputProcessorChainImpl inputProcessorChain = new InputProcessorChainImpl(securityContext, documentContext); diff --git a/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamWriterTest.java b/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamWriterTest.java index b2f395769d..fa956870c2 100644 --- a/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamWriterTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/XMLSecurityStreamWriterTest.java @@ -63,7 +63,7 @@ public void setUp() throws Exception { @Test public void testIdentityTransformResult() throws Exception { StringWriter securityStringWriter = new StringWriter(); - OutboundSecurityContextImpl securityContext = new OutboundSecurityContextImpl(); + OutboundSecurityContextImpl securityContext = new OutboundSecurityContextImpl(new XMLSecurityProperties()); OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(securityContext); outputProcessorChain.addProcessor(new EventWriterProcessor(securityStringWriter)); XMLSecurityStreamWriter xmlSecurityStreamWriter = new XMLSecurityStreamWriter(outputProcessorChain); @@ -196,7 +196,7 @@ public Iterator getPrefixes(String namespaceURI) { @Test public void testNullPrefix() throws Exception { StringWriter securityStringWriter = new StringWriter(); - OutboundSecurityContextImpl securityContext = new OutboundSecurityContextImpl(); + OutboundSecurityContextImpl securityContext = new OutboundSecurityContextImpl(new XMLSecurityProperties()); OutputProcessorChainImpl outputProcessorChain = new OutputProcessorChainImpl(securityContext); outputProcessorChain.addProcessor(new EventWriterProcessor(securityStringWriter)); XMLSecurityStreamWriter xmlSecurityStreamWriter = new XMLSecurityStreamWriter(outputProcessorChain); diff --git a/src/test/java/org/apache/xml/security/test/stax/encryption/EncryptionCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/encryption/EncryptionCreationTest.java index 995bce64f6..f4184cc622 100644 --- a/src/test/java/org/apache/xml/security/test/stax/encryption/EncryptionCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/encryption/EncryptionCreationTest.java @@ -215,7 +215,7 @@ public void testExceptionOnElementToEncryptNotFound() throws Exception { properties.setEncryptionSymAlgorithm("http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); SecurePart securePart = - new SecurePart(new QName("urn:example:po", "NotExistingElement"), SecurePart.Modifier.Content); + new SecurePart(new QName("urn:example:po", "NonExistingElement"), SecurePart.Modifier.Content); properties.addEncryptionPart(securePart); OutboundXMLSec outboundXMLSec = XMLSec.getOutboundXMLSec(properties); @@ -233,7 +233,7 @@ public void testExceptionOnElementToEncryptNotFound() throws Exception { fail("Exception expected"); } catch (XMLStreamException e) { assertTrue(e.getCause() instanceof XMLSecurityException); - assertEquals("Part to encrypt not found: {urn:example:po}NotExistingElement", e.getCause().getMessage()); + assertEquals("Too few (0/1) elements found to encrypt: {urn:example:po}NonExistingElement", e.getCause().getMessage()); } } @@ -1718,7 +1718,7 @@ private void testEncryptionIdToEncrypt(SecurePart securePart) throws Exception { "\n"; XMLSecurityProperties properties = new XMLSecurityProperties(); properties.setIdAttributeNS(new QName("attr1")); - properties.setActions(Collections.singletonList(XMLSecurityConstants.ENCRYPT)); + properties.setActions(Collections.singletonList(XMLSecurityConstants.ENCRYPTION)); properties.addEncryptionPart(securePart); byte[] bits192 = "abcdefghijklmnopqrstuvwx".getBytes(StandardCharsets.US_ASCII); SecretKey transportKey = new SecretKeySpec(bits192, "AES"); @@ -1751,7 +1751,7 @@ public void testEncryptionIdToSecureSupersedesName() throws Exception { "\n"; XMLSecurityProperties properties = new XMLSecurityProperties(); properties.setIdAttributeNS(new QName("attr1")); - properties.setActions(Collections.singletonList(XMLSecurityConstants.ENCRYPT)); + properties.setActions(Collections.singletonList(XMLSecurityConstants.ENCRYPTION)); SecurePart securePart = new SecurePart(new QName("Branch1"), SecurePart.Modifier.Element); securePart.setIdToSecure("def"); properties.addEncryptionPart(securePart); diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureCreationTest.java index cf76f2d6f1..9768db8326 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureCreationTest.java @@ -35,6 +35,7 @@ import org.apache.xml.security.signature.XMLSignature; import org.apache.xml.security.signature.XMLSignatureInput; import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; import org.apache.xml.security.test.dom.DSNamespaceContext; import org.apache.xml.security.test.stax.utils.XMLSecEventAllocator; import org.apache.xml.security.utils.resolver.ResourceResolverContext; @@ -46,6 +47,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; +import static org.apache.xml.security.test.stax.utils.TestUtils.toSecureParts; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -107,18 +109,18 @@ public void createXMLInputFactory() throws Exception { protected void verifyUsingDOM( Document document, X509Certificate cert, - List secureParts + List securePartSelectors ) throws Exception { - verifyUsingDOM(document, cert, secureParts, null); + verifyUsingDOM(document, cert, securePartSelectors, null); } protected void verifyUsingDOM( Document document, X509Certificate cert, - List secureParts, + List securePartSelectors, boolean secureValidation ) throws Exception { - verifyUsingDOM(document, cert, secureParts, null, + verifyUsingDOM(document, cert, securePartSelectors, null, true, "Id", secureValidation); } @@ -128,10 +130,10 @@ protected void verifyUsingDOM( protected void verifyUsingDOM( Document document, X509Certificate cert, - List secureParts, + List securePartSelectors, ResourceResolverSpi resourceResolverSpi ) throws Exception { - verifyUsingDOM(document, cert, secureParts, resourceResolverSpi, true, "Id", true); + verifyUsingDOM(document, cert, securePartSelectors, resourceResolverSpi, true, "Id", true); } /** @@ -140,12 +142,13 @@ protected void verifyUsingDOM( protected void verifyUsingDOM( Document document, X509Certificate cert, - List secureParts, + List securePartSelectors, ResourceResolverSpi resourceResolverSpi, boolean keyInfoRequired, String idAttributeNS, boolean secureValidation ) throws Exception { + List secureParts = toSecureParts(document, securePartSelectors); XPath xpath = getXPath(); String expression = "//dsig:Signature[1]"; @@ -182,8 +185,9 @@ protected void verifyUsingDOM( protected void verifyUsingDOM( Document document, Key key, - List secureParts + List securePartSelectors ) throws Exception { + List secureParts = toSecureParts(document, securePartSelectors); XPath xpath = getXPath(); String expression = "//dsig:Signature[1]"; @@ -206,8 +210,9 @@ protected void verifyUsingDOM( protected void verifyUsingDOMWithoutId( Document document, Key key, - List secureParts + List securePartSelectors ) throws Exception { + List secureParts = toSecureParts(document, securePartSelectors); XPath xpath = getXPath(); String expression = "//dsig:Signature[1]"; @@ -234,8 +239,9 @@ protected void verifyUsingDOMWithoutId( protected void verifyUsingDOMWithoutIdAndDefaultTransform ( Document document, Key key, - List secureParts + List securePartSelectors ) throws Exception { + List secureParts = toSecureParts(document, securePartSelectors); XPath xpath = getXPath(); String expression = "//dsig:Signature[1]"; diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java index 51a0f81c57..529fc3c185 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java @@ -104,7 +104,7 @@ public void testRSA_SHA1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -147,7 +147,7 @@ public void testRSA_SHA256() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -190,7 +190,7 @@ public void testRSA_SHA384() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -233,7 +233,7 @@ public void testRSA_SHA512() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -278,7 +278,7 @@ public void testRSA_RIPEMD160() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -323,7 +323,7 @@ public void testRSA_SHA1_MGF1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -368,7 +368,7 @@ public void testRSA_SHA224_MGF1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -413,7 +413,7 @@ public void testRSA_SHA256_MGF1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -458,7 +458,7 @@ public void testRSA_SHA384_MGF1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -503,7 +503,7 @@ public void testRSA_SHA512_MGF1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -549,7 +549,7 @@ public void testRSA_SSA_PSS() throws Exception { } // Verify using DOM - verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -592,7 +592,7 @@ public void testECDSA_SHA1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -635,7 +635,7 @@ public void testECDSA_SHA224() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -678,7 +678,7 @@ public void testECDSA_SHA256() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -721,7 +721,7 @@ public void testECDSA_SHA384() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -764,7 +764,7 @@ public void testECDSA_SHA512() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } @Test @@ -809,7 +809,7 @@ public void testECDSA_RIPEMD160() throws Exception { } // Verify using DOM - verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignatureSecureParts()); + verifyUsingDOM(document, ecKeyPair.getPublic(), properties.getSignaturePartSelectors()); } diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationReferenceURIResolverTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationReferenceURIResolverTest.java index 09aa7371c4..6b7fa17402 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationReferenceURIResolverTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationReferenceURIResolverTest.java @@ -108,7 +108,7 @@ public void testSignatureCreationWithExternalFilesystemXMLReference() throws Exc } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts(), false); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors(), false); } @Test @@ -159,7 +159,7 @@ public void testSignatureCreationWithExternalFilesystemBinaryReference() throws } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts(), false); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors(), false); } @Test @@ -217,7 +217,7 @@ public void testSignatureCreationWithExternalHttpReference() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts(), resolverDirectHTTP); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors(), resolverDirectHTTP); } finally { HttpRequestRedirectorProxy.stopHttpEngine(); } @@ -271,6 +271,6 @@ public void testSignatureCreationWithSameDocumentXPointerIdApostropheReference() assertTrue(uri.startsWith("#xpointer")); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } } \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java index 0d227b5c9f..96730ac1b8 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java @@ -64,6 +64,7 @@ import static org.apache.xml.security.stax.ext.XMLSecurityConstants.NS_C14N_EXCL; import static org.apache.xml.security.stax.ext.XMLSecurityConstants.NS_XMLDSIG_ENVELOPED_SIGNATURE; +import static org.apache.xml.security.test.stax.utils.TestUtils.toSecureParts; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -127,7 +128,7 @@ public void testSignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -180,7 +181,7 @@ public void testSignatureCreationRetrieveSignatureValue() throws Exception { assertNotNull(sigValueEvent.getSignatureValue()); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -203,7 +204,7 @@ public void testExceptionOnElementToSignNotFound() throws Exception { properties.setSignatureCerts(new X509Certificate[]{cert}); SecurePart securePart = - new SecurePart(new QName("urn:example:po", "NotExistingElement"), SecurePart.Modifier.Content); + new SecurePart(new QName("urn:example:po", "NonExistingElement"), SecurePart.Modifier.Content); properties.addSignaturePart(securePart); OutboundXMLSec outboundXMLSec = XMLSec.getOutboundXMLSec(properties); @@ -221,7 +222,7 @@ public void testExceptionOnElementToSignNotFound() throws Exception { fail("Exception expected"); } catch (XMLStreamException e) { assertTrue(e.getCause() instanceof XMLSecurityException); - assertEquals("Part to sign not found: {urn:example:po}NotExistingElement", e.getCause().getMessage()); + assertEquals("Too few (0/1) elements found to sign: {urn:example:po}NonExistingElement", e.getCause().getMessage()); } } @@ -286,7 +287,7 @@ public void testEnvelopedSignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -350,7 +351,7 @@ public void testEnvelopedSignatureCreationC14n11() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -414,7 +415,7 @@ public void testSignRootElementInRequest() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -527,7 +528,7 @@ private void signAtSpecificPosition(int position, QName positionQName, boolean s assertEquals(childNode.getLocalName(), "Signature"); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -583,7 +584,7 @@ public void testIdAttributeNS() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts(), null, true, "ID", true); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors(), null, true, "ID", true); } @@ -632,7 +633,7 @@ public void testMultipleElements() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -697,7 +698,7 @@ public void testMultipleSignatures() throws Exception { (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET); assertTrue(sigElements.getLength() == 2); - for (SecurePart secPart : properties.getSignatureSecureParts()) { + for (SecurePart secPart : toSecureParts(document, properties.getSignaturePartSelectors())) { if (secPart.getName() == null) { continue; } @@ -752,7 +753,7 @@ public void testHMACSignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -800,7 +801,7 @@ public void testStrongSignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -863,7 +864,7 @@ public void testDSASignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -921,7 +922,7 @@ public void testECDSASignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -980,7 +981,7 @@ public void testStrongECDSASignatureCreation() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1027,7 +1028,7 @@ public void testDifferentC14nMethod() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1095,7 +1096,7 @@ public void testDifferentC14nMethodForReference() throws Exception { assertEquals(XMLSecurityConstants.NS_XMLDSIG_SHA1, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1163,7 +1164,7 @@ public void testDifferentDigestMethodForReference() throws Exception { assertEquals("http://www.w3.org/2001/04/xmlenc#sha256", element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1210,7 +1211,7 @@ public void testC14n11Method() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1263,7 +1264,7 @@ public void testExcC14nInclusivePrefixes() throws Exception { assertEquals("", ((Element)nodeList.item(1)).getAttribute(XMLSecurityConstants.ATT_NULL_PrefixList.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1309,7 +1310,7 @@ public void testSignatureCreationRSAKeyValue() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1368,7 +1369,7 @@ public void testSignatureCreationECDSAKeyValue() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1423,7 +1424,7 @@ public void testSignatureCreationSKI() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1469,7 +1470,7 @@ public void testSignatureCreationX509Certificate() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1515,7 +1516,7 @@ public void testSignatureCreationX509SubjectName() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1565,7 +1566,7 @@ public void testSignatureCreationMultipleKeyIdentifiers() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1613,7 +1614,7 @@ public void testSignatureCreationTransformBase64() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1661,7 +1662,7 @@ public void testNoKeyInfo() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts(), null, false, "Id", true); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors(), null, false, "Id", true); } @@ -1713,7 +1714,7 @@ public void testSignatureCreationKeyName() throws Exception { assertEquals(cert.getIssuerDN().getName(), nodeList.item(0).getFirstChild().getTextContent()); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -1763,7 +1764,7 @@ public void testSignatureCreationWithoutId() throws Exception { assertEquals(cert.getIssuerDN().getName(), nodeList.item(0).getFirstChild().getTextContent()); // Verify using DOM - verifyUsingDOMWithoutId(document, cert.getPublicKey(), properties.getSignatureSecureParts()); + verifyUsingDOMWithoutId(document, cert.getPublicKey(), properties.getSignaturePartSelectors()); } @Test @@ -1818,6 +1819,6 @@ public void testSignatureCreationWithoutOmittedDefaultTransform() throws Excepti assertEquals(cert.getIssuerDN().getName(), nodeList.item(0).getFirstChild().getTextContent()); // Verify using DOM - verifyUsingDOMWithoutIdAndDefaultTransform(document, cert.getPublicKey(), properties.getSignatureSecureParts()); + verifyUsingDOMWithoutIdAndDefaultTransform(document, cert.getPublicKey(), properties.getSignaturePartSelectors()); } } diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureDigestCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureDigestCreationTest.java index 9f91975188..6ca64f52e6 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureDigestCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureDigestCreationTest.java @@ -105,7 +105,7 @@ public void testSHA1() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -160,7 +160,7 @@ public void testSHA224() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -215,7 +215,7 @@ public void testSHA256() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -270,7 +270,7 @@ public void testSHA384() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -325,7 +325,7 @@ public void testSHA512() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -382,7 +382,7 @@ public void testRIPEMD160() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -439,7 +439,7 @@ public void testWhirlpool() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -496,7 +496,7 @@ public void testSHA3_224() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -553,7 +553,7 @@ public void testSHA3_256() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -610,7 +610,7 @@ public void testSHA3_384() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } @Test @@ -667,7 +667,7 @@ public void testSHA3_512() throws Exception { assertEquals(digestAlgorithm, element.getAttribute(XMLSecurityConstants.ATT_NULL_Algorithm.getLocalPart())); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); } } \ No newline at end of file diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureEncryptionTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureEncryptionTest.java index 649d584234..ffa989472b 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureEncryptionTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureEncryptionTest.java @@ -123,7 +123,7 @@ public void testSignatureEncryption() throws Exception { assertEquals(nodeList.getLength(), 1); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getSignaturePartSelectors()); TestSecurityEventListener testSecurityEventListener = verifyUsingStAX(baos.toByteArray(), encryptionKey, cert.getPublicKey()); @@ -192,7 +192,7 @@ public void testSignatureEncryptionSameElement() throws Exception { assertEquals(nodeList.getLength(), 1); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getEncryptionPartSelectors()); TestSecurityEventListener testSecurityEventListener = verifyUsingStAX(baos.toByteArray(), encryptionKey, cert.getPublicKey()); @@ -269,7 +269,7 @@ public void testEnvelopedSignatureEncryptionElement() throws Exception { assertEquals(nodeList.getLength(), 1); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getEncryptionPartSelectors()); TestSecurityEventListener testSecurityEventListener = verifyUsingStAX(baos.toByteArray(), encryptionKey, cert.getPublicKey()); @@ -346,7 +346,7 @@ public void testEnvelopedSignatureEncryptionContent() throws Exception { assertEquals(nodeList.getLength(), 1); // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getEncryptionPartSelectors()); TestSecurityEventListener testSecurityEventListener = verifyUsingStAX(baos.toByteArray(), encryptionKey, cert.getPublicKey()); @@ -415,7 +415,7 @@ public void testEncryptionSignature() throws Exception { } // Verify using DOM - verifyUsingDOM(document, cert, properties.getSignatureSecureParts()); + verifyUsingDOM(document, cert, properties.getEncryptionPartSelectors()); // Decrypt using DOM API Document doc = diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureHMACCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureHMACCreationTest.java index dbddfb68bf..24c20cc204 100644 --- a/src/test/java/org/apache/xml/security/test/stax/signature/SignatureHMACCreationTest.java +++ b/src/test/java/org/apache/xml/security/test/stax/signature/SignatureHMACCreationTest.java @@ -89,7 +89,7 @@ public void testHMACSHA1() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -134,7 +134,7 @@ public void testHMACSHA_224() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -179,7 +179,7 @@ public void testHMACSHA_256() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -224,7 +224,7 @@ public void testHMACSHA_384() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -269,7 +269,7 @@ public void testHMACSHA_512() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } @Test @@ -316,7 +316,7 @@ public void testRIPEMD160() throws Exception { } // Verify using DOM - verifyUsingDOM(document, key, properties.getSignatureSecureParts()); + verifyUsingDOM(document, key, properties.getSignaturePartSelectors()); } diff --git a/src/test/java/org/apache/xml/security/test/stax/utils/TestUtils.java b/src/test/java/org/apache/xml/security/test/stax/utils/TestUtils.java new file mode 100644 index 0000000000..24f44a9dfa --- /dev/null +++ b/src/test/java/org/apache/xml/security/test/stax/utils/TestUtils.java @@ -0,0 +1,153 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.xml.security.test.stax.utils; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.xml.security.stax.ext.SecurePart; +import org.apache.xml.security.stax.ext.SecurePartSelector; +import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; +import org.apache.xml.security.stax.ext.stax.XMLSecNamespace; +import org.apache.xml.security.stax.ext.stax.XMLSecStartElement; +import org.apache.xml.security.stax.impl.stax.XMLSecAttributeImpl; +import org.apache.xml.security.stax.impl.stax.XMLSecNamespaceImpl; +import org.apache.xml.security.stax.impl.stax.XMLSecStartElementImpl; +import org.apache.xml.security.utils.KeyValue; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.traversal.DocumentTraversal; +import org.w3c.dom.traversal.NodeFilter; +import org.w3c.dom.traversal.TreeWalker; + +public class TestUtils { + + public static List toSecureParts(Document document, List securePartSelectors) { + List secureParts = new ArrayList<>(securePartSelectors.size()); + TreeWalker walker = ((DocumentTraversal) document).createTreeWalker(document.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true); + Map elementsByNode = new IdentityHashMap<>(); + for (Node node = walker.getCurrentNode(); node != null; node = walker.nextNode()) { + QName name = convertNodeToQName(node); + KeyValue, List> attributesAndNamespaces = convertNodeToAttributesAndNamespaces(node); + List attributes = attributesAndNamespaces.getKey(); + List namespaces = attributesAndNamespaces.getValue(); + XMLSecStartElement parent = elementsByNode.get(node.getParentNode()); + XMLSecStartElement element = new XMLSecStartElementImpl(name, attributes, namespaces, parent); + elementsByNode.put(node, element); + for (SecurePartSelector securePartSelector : securePartSelectors) { + SecurePart securePart = securePartSelector.select(element); + if (securePart != null) { + secureParts.add(securePart); + break; + } + } + } + return secureParts; + } + + public static Matcher containsRegex(String pattern) { + return containsRegex(pattern, true, 1); + } + + public static Matcher containsRegex(Pattern pattern) { + return containsRegex(pattern, true, 1); + } + + public static Matcher containsRegex(String pattern, int times) { + return containsRegex(pattern, false, times); + } + + public static Matcher containsRegex(Pattern pattern, int times) { + return containsRegex(pattern, false, times); + } + + public static Matcher containsRegex(String pattern, boolean atLeast, int times) { + return containsRegex(Pattern.compile(pattern), atLeast, times); + } + + public static Matcher containsRegex(Pattern pattern, boolean atLeast, int times) { + return new TypeSafeDiagnosingMatcher() { + + @Override + public void describeTo(Description description) { + description.appendText("a string containing the pattern ").appendValue(pattern) + .appendText(atLeast ? " at least " : " exactly ").appendValue(times).appendText(" times"); + } + + @Override + protected boolean matchesSafely(String actual, Description mismatchDescription) { + java.util.regex.Matcher matcher = pattern.matcher(actual); + int found = 0; + while (matcher.find()) { + found++; + } + boolean matches = atLeast ? found >= times : found == times; + if (!matches) { + mismatchDescription.appendText("the string was ").appendValue(actual); + } + return matches; + } + }; + } + + public static QName convertNodeToQName(Node node) { + String namespaceURI = node.getNamespaceURI(); + if (namespaceURI == null) { + namespaceURI = XMLConstants.NULL_NS_URI; + } + String prefix = node.getPrefix(); + if (prefix == null) { + prefix = XMLConstants.DEFAULT_NS_PREFIX; + } + String localName = node.getLocalName(); + if (localName == null) { + throw new IllegalArgumentException("Local name is null, indicating that DOM level 2 is not supported while it is required. If created using a DocumentBuilder, be sure to setNamespaceAware(true)."); + } + return new QName(namespaceURI, localName, prefix); + } + + public static KeyValue, List> convertNodeToAttributesAndNamespaces(Node node) { + NamedNodeMap attributesAndNamespaces = node.getAttributes(); + List attributes = new ArrayList<>(attributesAndNamespaces.getLength()); + List namespaces = new ArrayList<>(attributesAndNamespaces.getLength()); + for (int i = 0, n = attributesAndNamespaces.getLength(); i != n; i++) { + Attr attr = (Attr) attributesAndNamespaces.item(i); + if (attr.getName().equals("xmlns")) { + namespaces.add(XMLSecNamespaceImpl.getInstance(null, attr.getValue())); + } else if (attr.getName().startsWith("xmlns:")) { + namespaces.add(XMLSecNamespaceImpl.getInstance(attr.getName().substring(6), attr.getValue())); + } else { + QName name = convertNodeToQName(attr); + attributes.add(new XMLSecAttributeImpl(name, attr.getValue())); + } + } + return new KeyValue<>(attributes, namespaces); + } +} diff --git a/src/test/java/org/apache/xml/security/test/stax/utils/TestUtilsTest.java b/src/test/java/org/apache/xml/security/test/stax/utils/TestUtilsTest.java new file mode 100644 index 0000000000..3753ee6ae7 --- /dev/null +++ b/src/test/java/org/apache/xml/security/test/stax/utils/TestUtilsTest.java @@ -0,0 +1,77 @@ +package org.apache.xml.security.test.stax.utils; + +import java.io.StringReader; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.xml.security.stax.ext.stax.XMLSecAttribute; +import org.apache.xml.security.stax.ext.stax.XMLSecNamespace; +import org.apache.xml.security.utils.KeyValue; +import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import static org.apache.xml.security.test.stax.utils.TestUtils.convertNodeToAttributesAndNamespaces; +import static org.apache.xml.security.test.stax.utils.TestUtils.convertNodeToQName; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +public class TestUtilsTest { + + @Test + public void testConvertNodeToAttributesAndNamespace() throws Exception { + String xml = ""; + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + Document document = documentBuilderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); + Node node = document.getFirstChild(); + QName name = convertNodeToQName(node); + assertThat(name.getLocalPart(), is(equalTo("localPart"))); + assertThat(name.getNamespaceURI(), is(equalTo("urn:test:ns"))); + assertThat(name.getPrefix(), is(equalTo("prefix"))); + KeyValue, List> attributesAndNamespaces = convertNodeToAttributesAndNamespaces(node); + List attributes = attributesAndNamespaces.getKey(); + List namespaces = attributesAndNamespaces.getValue(); + assertThat(namespaces.size(), is(2)); + int namespaceIndex1 = 0; + for (XMLSecNamespace namespace : namespaces) { + if (namespace.getPrefix().equals("prefix")) { + break; + } + namespaceIndex1++; + } + int namespaceIndex2 = (namespaceIndex1 + 1) % namespaces.size(); + XMLSecNamespace namespace1 = namespaces.get(namespaceIndex1); + assertThat(namespace1.getPrefix(), is(equalTo("prefix"))); + assertThat(namespace1.getNamespaceURI(), is(equalTo("urn:test:ns"))); + assertThat(namespace1.isDefaultNamespaceDeclaration(), is(false)); + XMLSecNamespace namespace2 = namespaces.get(namespaceIndex2); + assertThat(namespace2.getPrefix(), is(equalTo(XMLConstants.DEFAULT_NS_PREFIX))); + assertThat(namespace2.getNamespaceURI(), is(equalTo("urn:test:default-ns"))); + assertThat(namespace2.isDefaultNamespaceDeclaration(), is(true)); + assertThat(attributes.size(), is(2)); + int attrIndex1 = 0; + for (XMLSecAttribute attribute : attributes) { + if (attribute.getValue().equals("val1")) { + break; + } + attrIndex1++; + } + int attrIndex2 = (attrIndex1 + 1) % attributes.size(); + XMLSecAttribute attr1 = attributes.get(attrIndex1); + assertThat(attr1.getAttributeNamespace(), is(equalTo(namespace1))); + assertThat(attr1.getName().getLocalPart(), is(equalTo("attr1"))); + assertThat(attr1.getName().getNamespaceURI(), is(equalTo("urn:test:ns"))); + assertThat(attr1.getValue(), is(equalTo("val1"))); + XMLSecAttribute attr2 = attributes.get(attrIndex2); + assertThat(attr2.getAttributeNamespace(), is(equalTo(namespace2))); + assertThat(attr2.getName().getLocalPart(), is(equalTo("attr2"))); + assertThat(attr2.getName().getNamespaceURI(), is(equalTo(XMLConstants.NULL_NS_URI))); + assertThat(attr2.getValue(), is(equalTo("val2"))); + } +}