/** * 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.wss4j.performance; import org.apache.wss4j.common.bsp.BSPRule; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoFactory; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.util.XMLUtils; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.dom.WSSConfig; import org.apache.wss4j.dom.WSSecurityEngineResult; import org.apache.wss4j.dom.common.SecurityTestUtil; import org.apache.wss4j.dom.handler.HandlerAction; import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.handler.WSHandler; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.handler.WSHandlerResult; import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.stax.ConfigurationConverter; import org.apache.wss4j.stax.WSSec; import org.apache.wss4j.stax.ext.InboundWSSec; import org.apache.wss4j.stax.ext.OutboundWSSec; import org.apache.wss4j.stax.ext.WSSConstants; import org.apache.wss4j.stax.ext.WSSSecurityProperties; import org.apache.wss4j.stax.impl.processor.input.DecryptInputProcessor; import org.apache.wss4j.stax.test.WSS4JCallbackHandlerImpl; import org.apache.wss4j.stax.test.utils.SOAPUtil; import org.apache.wss4j.stax.test.utils.StAX2DOM; import org.apache.wss4j.stax.test.utils.XmlReaderToWriter; import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.stax.impl.InboundSecurityContextImpl; import org.apache.xml.security.stax.impl.processor.input.AbstractDecryptInputProcessor; import org.apache.xml.security.stax.impl.processor.input.AbstractSignatureReferenceVerifyInputProcessor; import org.apache.xml.security.stax.impl.processor.input.XMLEventReaderInputProcessor; import org.apache.xml.security.stax.securityEvent.SecurityEvent; import org.apache.xml.security.stax.securityEvent.SecurityEventConstants; import org.apache.xml.security.stax.securityEvent.SecurityEventListener; import org.junit.AfterClass; import org.junit.Assert; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.security.auth.callback.CallbackHandler; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; public abstract class AbstractTestBase extends org.junit.Assert { //javax.xml.transform.Transformer transformer = TransformerFactory.newInstance().newTransformer(); //transformer.transform(new StreamSource(new ByteArrayInputStream(baos.toByteArray())), new StreamResult(System.out)); protected static final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); protected static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); protected DocumentBuilderFactory documentBuilderFactory; protected static final String SECURED_DOCUMENT = "securedDocument"; static { LogManager.getLogManager().addLogger(Logger.getLogger("org.jcp.xml.dsig.internal.dom")); LogManager.getLogManager().getLogger("org.jcp.xml.dsig.internal.dom").setLevel(Level.FINE); WSSConfig.init(); } @AfterClass public static void cleanup() throws Exception { SecurityTestUtil.cleanup(); } public AbstractTestBase() { documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); documentBuilderFactory.setIgnoringComments(false); documentBuilderFactory.setCoalescing(false); documentBuilderFactory.setIgnoringElementContentWhitespace(false); xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, false); xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); //xmlInputFactory.setProperty(WstxInputProperties.P_MIN_TEXT_SEGMENT, new Integer(5 * 8192)); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), null); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream, SecurityEventListener securityEventListener) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), securityEventListener); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream, List<SecurityEvent> securityEventList, SecurityEventListener securityEventListener) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), securityEventList, securityEventListener); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { return doInboundSecurity(securityProperties, xmlStreamReader, null); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader, SecurityEventListener securityEventListener) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { return doInboundSecurity(securityProperties, xmlStreamReader, new ArrayList<>(), securityEventListener); } public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader, List<SecurityEvent> securityEventList, SecurityEventListener securityEventListener) throws XMLStreamException, ParserConfigurationException, XMLSecurityException { InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties); XMLStreamReader outXmlStreamReader = wsSecIn.processInMessage(xmlStreamReader, securityEventList, securityEventListener); return StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), outXmlStreamReader); } protected ByteArrayOutputStream doOutboundSecurity(WSSSecurityProperties securityProperties, InputStream sourceDocument) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties); XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, "UTF-8", new ArrayList<>()); XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument); XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter); xmlStreamWriter.close(); return baos; } protected ByteArrayOutputStream doOutboundSecurity(Map<String, Object> config, InputStream sourceDocument) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config); OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties); XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, "UTF-8", new ArrayList<>()); XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument); XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter); xmlStreamWriter.close(); return baos; } protected Document doOutboundSecurityWithWSS4J(InputStream sourceDocument, String action, Properties properties) throws WSSecurityException, TransformerException { Map<String, Object> context = doOutboundSecurityWithWSS4J_1(sourceDocument, action, properties); return (Document) context.get(SECURED_DOCUMENT); } protected Map<String, Object> doOutboundSecurityWithWSS4J_1( InputStream sourceDocument, String action, final Properties properties ) throws WSSecurityException, TransformerException { CustomWSS4JHandler wss4JHandler = new CustomWSS4JHandler(); final Map<String, Object> messageContext = getMessageContext(sourceDocument); messageContext.put(WSHandlerConstants.ACTION, action); messageContext.put(WSHandlerConstants.USER, "transmitter"); Properties sigProperties = new Properties(); sigProperties.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"); sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.file", "transmitter.jks"); sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.password", "default"); //sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.alias", "transmitter"); wss4JHandler.setPassword(messageContext, "default"); messageContext.put(WSHandlerConstants.SIG_PROP_REF_ID, "" + sigProperties.hashCode()); messageContext.put("" + sigProperties.hashCode(), sigProperties); Properties encProperties = new Properties(); encProperties.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"); encProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.file", "transmitter.jks"); encProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.password", "default"); //sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.alias", "transmitter"); wss4JHandler.setPassword(messageContext, "default"); messageContext.put(WSHandlerConstants.ENCRYPTION_USER, "receiver"); messageContext.put(WSHandlerConstants.ENC_PROP_REF_ID, "" + encProperties.hashCode()); messageContext.put("" + encProperties.hashCode(), encProperties); Enumeration<?> enumeration = properties.propertyNames(); while (enumeration.hasMoreElements()) { String s = (String) enumeration.nextElement(); messageContext.put(s, properties.get(s)); } RequestData requestData = new RequestData(); requestData.setMsgContext(messageContext); requestData.setCallbackHandler(new WSS4JCallbackHandlerImpl()); requestData.setWssConfig(WSSConfig.getNewInstance()); wss4JHandler.doSender(messageContext, requestData, true); return messageContext; } protected Document doInboundSecurityWithWSS4J(Document document, String action) throws Exception { Map<String, Object> messageContext = doInboundSecurityWithWSS4J_1(document, action); return ((Document) messageContext.get(SECURED_DOCUMENT)); } protected Map<String, Object> doInboundSecurityWithWSS4J_1(Document document, String action) throws Exception { return doInboundSecurityWithWSS4J_1(document, action, new Properties(), false); } protected Map<String, Object> doInboundSecurityWithWSS4J_1( Document document, String action, Properties properties, boolean client ) throws Exception { CustomWSS4JHandler wss4JHandler = new CustomWSS4JHandler(); Map<String, Object> messageContext = getMessageContext(document); messageContext.put(WSHandlerConstants.ACTION, action); if (client) { messageContext.put(WSHandlerConstants.USER, "transmitter"); } else { messageContext.put(WSHandlerConstants.USER, "receiver"); } if (properties.get(WSHandlerConstants.PW_CALLBACK_REF) != null) { messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, properties.get(WSHandlerConstants.PW_CALLBACK_REF)); } else { messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, new WSS4JCallbackHandlerImpl()); } messageContext.put(WSHandlerConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, "false"); Enumeration<?> enumeration = properties.propertyNames(); while (enumeration.hasMoreElements()) { String s = (String) enumeration.nextElement(); messageContext.put(s, properties.get(s)); } RequestData requestData = new RequestData(); requestData.setMsgContext(messageContext); if (client) { final Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties"); requestData.setDecCrypto(crypto); requestData.setSigVerCrypto(crypto); } else { final Crypto crypto = CryptoFactory.getInstance("receiver-crypto.properties"); requestData.setDecCrypto(crypto); requestData.setSigVerCrypto(crypto); } if (properties.get(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD) != null) { messageContext.put(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, properties.get(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD)); } else if (WSHandlerConstants.USERNAME_TOKEN_SIGNATURE.equals(action)) { messageContext.put(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, "true"); } // Disable PrefixList checking as the stax code doesn't support this yet //todo List<BSPRule> ignoredRules = new ArrayList<>(); ignoredRules.add(BSPRule.R5404); ignoredRules.add(BSPRule.R5406); ignoredRules.add(BSPRule.R5407); ignoredRules.add(BSPRule.R5417); ignoredRules.add(BSPRule.R3063); ignoredRules.add(BSPRule.R5620); ignoredRules.add(BSPRule.R5621); //ignoredRules.add(BSPRule.R5215); requestData.setIgnoredBSPRules(ignoredRules); wss4JHandler.doReceiver(messageContext, requestData, false); return messageContext; } protected Map<String, Object> getMessageContext(InputStream inputStream) { Map<String, Object> context = new HashMap<>(); try { context.put(SECURED_DOCUMENT, SOAPUtil.toSOAPPart(inputStream)); } catch (Exception e) { throw new RuntimeException(e); } return context; } private Map<String, Object> getMessageContext(Document document) { Map<String, Object> context = new HashMap<>(); context.put(SECURED_DOCUMENT, document); return context; } protected XPathExpression getXPath(String expression) throws XPathExpressionException { XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xPath = xPathFactory.newXPath(); xPath.setNamespaceContext( new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if (WSSConstants.PREFIX_DSIG.equals(prefix)) { return WSSConstants.NS_DSIG; } else if (WSSConstants.PREFIX_SOAPENV.equals(prefix)) { return WSSConstants.NS_SOAP11; } else if (WSSConstants.PREFIX_WSSE.equals(prefix)) { return WSSConstants.NS_WSSE10; } else if (WSSConstants.PREFIX_WSU.equals(prefix)) { return WSSConstants.NS_WSU10; } else if (WSSConstants.PREFIX_XENC.equals(prefix)) { return WSSConstants.NS_XMLENC; } else if (WSSConstants.PREFIX_XENC11.equals(prefix)) { return WSSConstants.NS_XMLENC11; } else { return null; } } @Override public String getPrefix(String namespaceURI) { if (WSSConstants.NS_DSIG.equals(namespaceURI)) { return WSSConstants.PREFIX_DSIG; } else if (WSSConstants.NS_SOAP11.equals(namespaceURI)) { return WSSConstants.PREFIX_SOAPENV; } else if (WSSConstants.NS_WSSE10.equals(namespaceURI)) { return WSSConstants.PREFIX_WSSE; } else if (WSSConstants.NS_WSU10.equals(namespaceURI)) { return WSSConstants.PREFIX_WSU; } else if (WSSConstants.NS_XMLENC.equals(namespaceURI)) { return WSSConstants.PREFIX_XENC; } else if (WSSConstants.NS_XMLENC11.equals(namespaceURI)) { return WSSConstants.PREFIX_XENC11; } else { return null; } } @Override public Iterator<String> getPrefixes(String namespaceURI) { return null; } } ); return xPath.compile(expression); } class CustomWSS4JHandler extends WSHandler { private final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(CustomWSS4JHandler.class.getName()); private final boolean doDebug = LOG.isDebugEnabled(); /** * Handles incoming web service requests and outgoing responses * * @throws TransformerException */ public boolean doSender(Map<String, Object> mc, RequestData reqData, boolean isRequest) throws WSSecurityException, TransformerException { /* * Get the action first. */ String action = (String) mc.get(WSHandlerConstants.ACTION); if (action == null) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: No action defined"); } List<HandlerAction> actions = WSSecurityUtil.decodeHandlerAction(action, null); if (actions.isEmpty()) { return true; } /* * For every action we need a username, so get this now. The username * defined in the deployment descriptor takes precedence. */ reqData.setUsername((String) getOption(WSHandlerConstants.USER)); if (reqData.getUsername() == null || reqData.getUsername().equals("")) { reqData.setUsername((String) mc.get(WSHandlerConstants.USER)); } /* * Now we perform some set-up for UsernameToken and Signature * functions. No need to do it for encryption only. Check if username * is available and then get a password. */ boolean usernameRequired = false; for (HandlerAction handlerAction : actions) { if (handlerAction.getAction() == WSConstants.SIGN || handlerAction.getAction() == WSConstants.UT || handlerAction.getAction() == WSConstants.UT_SIGN) { usernameRequired = true; break; } } if (usernameRequired && (reqData.getUsername() == null || reqData.getUsername().equals(""))) { /* * We need a username - if none throw a WSSecurityException. For encryption * there is a specific parameter to get a username. */ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: Empty username for specified action" ); } if (doDebug) { LOG.debug("Actor: " + reqData.getActor()); } /* * Now get the SOAP part from the request message and convert it into a * Document. * * Now we can perform our security operations on this request. */ Document doc = (Document) mc.get(SECURED_DOCUMENT); if (doc == null) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: cannot get SOAP envlope from message" ); } if (doDebug) { LOG.debug("WSS4JHandler: orginal SOAP request: "); LOG.debug(XMLUtils.prettyDocumentToString(doc)); } doSenderAction(doc, reqData, actions, isRequest); mc.put(SECURED_DOCUMENT, doc); return true; } @SuppressWarnings("unchecked") public boolean doReceiver(Map<String, Object> mc, RequestData reqData, boolean isRequest) throws WSSecurityException { String action = (String) mc.get(WSHandlerConstants.ACTION); if (action == null) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: No action defined"); } List<Integer> actions = WSSecurityUtil.decodeAction(action); String actor = (String) mc.get(WSHandlerConstants.ACTOR); Document doc = (Document) mc.get(SECURED_DOCUMENT); /* * Check if it's a fault. Don't process faults. */ org.apache.wss4j.dom.SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement()); if (WSSecurityUtil.findElement( doc.getDocumentElement(), "Fault", soapConstants.getEnvelopeURI()) != null ) { return false; } /* * To check a UsernameToken or to decrypt an encrypted message we need * a password. */ CallbackHandler cbHandler = getPasswordCallbackHandler(reqData); reqData.setCallbackHandler(cbHandler); /* * Get and check the Signature specific parameters first because they * may be used for encryption too. */ doReceiverAction(actions, reqData); Element elem = WSSecurityUtil.getSecurityHeader(doc, actor); List<WSSecurityEngineResult> wsResult = null; try { wsResult = secEngine.processSecurityHeader(elem, reqData); } catch (WSSecurityException ex) { if (doDebug) { LOG.debug(ex.getMessage(), ex); } throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: security processing failed", ex ); } if (wsResult == null || wsResult.isEmpty()) { // no security header found if (actions.isEmpty()) { return true; } else { throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "empty", "WSS4JHandler: Request does not contain required Security header" ); } } if (reqData.getWssConfig().isEnableSignatureConfirmation() && !isRequest) { checkSignatureConfirmation(reqData, wsResult); } if (doDebug) { LOG.debug("Processed received SOAP request"); } /* * now check the security actions: do they match, in right order? */ if (!checkReceiverResults(wsResult, actions)) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty", "WSS4JHandler: security processing failed (actions mismatch)" ); } /* * All ok up to this point. Now construct and setup the * security result structure. The service may fetch this * and check it. */ List<WSHandlerResult> results = null; if ((results = (List<WSHandlerResult>) mc.get(WSHandlerConstants.RECV_RESULTS)) == null) { results = new ArrayList<>(); mc.put(WSHandlerConstants.RECV_RESULTS, results); } WSHandlerResult rResult = new WSHandlerResult(actor, wsResult); results.add(0, rResult); if (doDebug) { LOG.debug("WSS4JHandler: exit invoke()"); } return true; } @Override protected boolean checkReceiverResults( List<WSSecurityEngineResult> wsResult, List<Integer> actions ) { List<WSSecurityEngineResult> wsSecurityEngineResults = new ArrayList<>(); for (WSSecurityEngineResult result : wsResult) { boolean found = false; for (WSSecurityEngineResult res : wsSecurityEngineResults) { if (result.get(WSSecurityEngineResult.TAG_ACTION).equals(res.get(WSSecurityEngineResult.TAG_ACTION))) { found = true; break; } } if (!found) { wsSecurityEngineResults.add(result); } } int size = actions.size(); int ai = 0; for (WSSecurityEngineResult result : wsSecurityEngineResults) { final Integer act = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION); if (act == WSConstants.SC || act == WSConstants.BST || act == WSConstants.DKT || act == WSConstants.SCT || act == WSConstants.UT_NOPASSWORD) { continue; } if (ai >= size || actions.get(ai++).intValue() != act) { return false; } } /* if (ai != size) { return false; } */ return true; } @Override public Object getOption(String key) { return null; } @SuppressWarnings("unchecked") @Override public Object getProperty(Object msgContext, String key) { return ((Map<String, Object>) msgContext).get(key); } @SuppressWarnings("unchecked") @Override public void setProperty(Object msgContext, String key, Object value) { ((Map<String, Object>) msgContext).put(key, value); } @SuppressWarnings("unchecked") @Override public String getPassword(Object msgContext) { return (String) ((Map<String, Object>) msgContext).get("password"); } @SuppressWarnings("unchecked") @Override public void setPassword(Object msgContext, String password) { ((Map<String, Object>) msgContext).put("password", password); } } protected class TestSecurityEventListener implements SecurityEventListener { private SecurityEventConstants.Event[] expectedEvents; private List<SecurityEvent> receivedSecurityEvents = new ArrayList<>(); public TestSecurityEventListener(SecurityEventConstants.Event[] expectedEvents) { this.expectedEvents = expectedEvents; } public List<SecurityEvent> getReceivedSecurityEvents() { return receivedSecurityEvents; } @SuppressWarnings("unchecked") public <T> T getSecurityEvent(SecurityEventConstants.Event securityEvent) { for (SecurityEvent event : receivedSecurityEvents) { if (event.getSecurityEventType() == securityEvent) { return (T) event; } } return null; } @SuppressWarnings("unchecked") public <T> List<T> getSecurityEvents(SecurityEventConstants.Event securityEvent) { List<T> foundEvents = new ArrayList<>(); for (SecurityEvent event : receivedSecurityEvents) { if (event.getSecurityEventType() == securityEvent) { foundEvents.add((T) event); } } return foundEvents; } @Override public void registerSecurityEvent(SecurityEvent securityEvent) throws WSSecurityException { Assert.assertNotNull(securityEvent.getCorrelationID()); Assert.assertNotEquals("", securityEvent.getCorrelationID()); receivedSecurityEvents.add(securityEvent); } public void compare() { if (expectedEvents.length != receivedSecurityEvents.size()) { printEvents(); Assert.fail("event count mismatch"); } boolean asserted = true; for (int i = 0; i < expectedEvents.length; i++) { if (!expectedEvents[i].equals(receivedSecurityEvents.get(i).getSecurityEventType())) { asserted = false; break; } } if (!asserted) { printEvents(); Assert.fail("event mismatch"); } } private void printEvents() { System.out.println("expected events:"); for (int i = 0; i < expectedEvents.length; i++) { SecurityEventConstants.Event expectedEvent = expectedEvents[i]; System.out.println("WSSecurityEventConstants." + expectedEvent + ","); } System.out.println("received events:"); for (int i = 0; i < receivedSecurityEvents.size(); i++) { SecurityEvent securityEvent = receivedSecurityEvents.get(i); System.out.println("WSSecurityEventConstants." + securityEvent.getSecurityEventType() + ","); } } } //sometimes I really like reflection. We can fix jdk bugs which will never be fixed, we can do other funny things and //we can also change "private static final" fields for testing:-) //But keep in mind that this only works for Objects and not primitive types. Primitive types will be inlined... public static void switchAllowNotSameDocumentReferences(Boolean value) throws NoSuchFieldException, IllegalAccessException { Field field = AbstractSignatureReferenceVerifyInputProcessor.class.getDeclaredField("allowNotSameDocumentReferences"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } public static void switchDoNotThrowExceptionForManifests(Boolean value) throws NoSuchFieldException, IllegalAccessException { Field field = AbstractSignatureReferenceVerifyInputProcessor.class.getDeclaredField("doNotThrowExceptionForManifests"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } public static int changeValueOfMaximumAllowedReferencesPerManifest(Integer value) throws NoSuchFieldException, IllegalAccessException { Field field = AbstractSignatureReferenceVerifyInputProcessor.class.getDeclaredField("maximumAllowedReferencesPerManifest"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Integer oldval = (Integer)field.get(null); field.set(null, value); return oldval; } public static int changeValueOfMaximumAllowedTransformsPerReference(Integer value) throws NoSuchFieldException, IllegalAccessException { Field field = AbstractSignatureReferenceVerifyInputProcessor.class.getDeclaredField("maximumAllowedTransformsPerReference"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Integer oldval = (Integer)field.get(null); field.set(null, value); return oldval; } public static void switchAllowMD5Algorithm(Boolean value) throws NoSuchFieldException, IllegalAccessException { Field field = InboundSecurityContextImpl.class.getDeclaredField("allowMD5Algorithm"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } public static int changeValueOfMaximumAllowedXMLStructureDepth(Integer value) throws NoSuchFieldException, IllegalAccessException { Field xmlEventReaderInputProcessorField = XMLEventReaderInputProcessor.class.getDeclaredField("maximumAllowedXMLStructureDepth"); xmlEventReaderInputProcessorField.setAccessible(true); Field abstractDecryptInputProcessorField = AbstractDecryptInputProcessor.class.getDeclaredField("maximumAllowedXMLStructureDepth"); abstractDecryptInputProcessorField.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(xmlEventReaderInputProcessorField, xmlEventReaderInputProcessorField.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(abstractDecryptInputProcessorField, abstractDecryptInputProcessorField.getModifiers() & ~Modifier.FINAL); Integer oldval = (Integer)xmlEventReaderInputProcessorField.get(null); xmlEventReaderInputProcessorField.set(null, value); abstractDecryptInputProcessorField.set(null, value); return oldval; } public static long changeValueOfMaximumAllowedDecompressedBytes(Long value) throws NoSuchFieldException, IllegalAccessException { Field field = DecryptInputProcessor.class.getDeclaredField("maximumAllowedDecompressedBytes"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Long oldval = (Long) field.get(null); field.set(null, value); return oldval; } public static Double getJavaSpecificationVersion() { String jsv = System.getProperty("java.specification.version"); if (jsv != null) { return Double.parseDouble(jsv); } return 0.0d; } }