blob: a41956058dbb19702563d25fd37315403ff01a15 [file] [log] [blame]
/**
* 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;
}
}