| /* |
| * Copyright 2003-2004 The Apache Software Foundation. |
| * |
| * Licensed 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 wssec; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| import org.apache.axis.AxisFault; |
| import org.apache.axis.Message; |
| import org.apache.axis.MessageContext; |
| import org.apache.axis.client.AxisClient; |
| import org.apache.axis.configuration.NullProvider; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.ws.axis.security.WSDoAllReceiver; |
| import org.apache.ws.axis.security.WSDoAllSender; |
| import org.apache.ws.security.WSPasswordCallback; |
| import org.apache.ws.security.components.crypto.BouncyCastle; |
| import org.apache.ws.security.components.crypto.Crypto; |
| import org.apache.ws.security.handler.WSHandlerConstants; |
| |
| import javax.security.auth.callback.Callback; |
| import javax.security.auth.callback.CallbackHandler; |
| import javax.security.auth.callback.UnsupportedCallbackException; |
| import java.io.ByteArrayInputStream; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.security.KeyStore; |
| |
| /** |
| * <dl> |
| * <dt><b>Title: </b><dd>WS Security Hooks Test Case</dd> |
| * <p> |
| * <dt><b>Description: </b><dd>Test Case to verify the load...Crypto hooks work properly. |
| * Also tests the setKeyStore method of Merlin </dd> |
| * </dl> |
| * |
| * @see org.apache.ws.security.components.crypto.Merlin#setKeyStore |
| * @see org.apache.ws.axis.security.WSDoAllReceiver#loadSignatureCrypto |
| * @see org.apache.ws.axis.security.WSDoAllReceiver#loadDecryptionCrypto |
| * @see org.apache.ws.axis.security.WSDoAllSender#loadSignatureCrypto |
| * @see org.apache.ws.axis.security.WSDoAllSender#loadEncryptionCrypto |
| * |
| * @author <a href="mailto:jasone@greenrivercomputing.com>Jason Essington</a> |
| * @version $Revision$ |
| */ |
| public class TestWSSecurityHooks extends TestCase implements CallbackHandler |
| { |
| private static Log log = LogFactory.getLog(TestWSSecurityHooks.class); |
| private static final String soapMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ |
| "<soapenv:Envelope " + |
| "xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" " + |
| "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + |
| "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + |
| "<soapenv:Header>" + |
| "</soapenv:Header>" + |
| "<soapenv:Body>" + |
| "<ns1:echo " + |
| "xmlns:ns1=\"http://org.apache.wss4j.wssec/TESTCASE\" " + |
| "soapenv:encodingStyle=\"http://www.w3.org/2003/05/soap-encoding\">" + |
| "<inStr xsi:type=\"xsd:string\">ECHO ECHo ECho Echo echo echO ecHO eCHO ECHO</inStr>" + |
| "</ns1:echo>" + |
| "</soapenv:Body>" + |
| "</soapenv:Envelope>"; |
| |
| KeyStore keystore = null; |
| MessageContext mc = null; |
| |
| public TestWSSecurityHooks(String name) { |
| super(name); |
| } |
| |
| protected void setUp() throws Exception { |
| AxisClient tmpEngine = new AxisClient(new NullProvider()); |
| mc = new MessageContext(tmpEngine); |
| mc.setCurrentMessage(getSOAPMessage(soapMessage)); |
| mc.setProperty(WSHandlerConstants.PW_CALLBACK_REF, this); |
| keystore = loadKeyStore(); |
| } |
| |
| public static Test suite() { |
| return new TestSuite(TestWSSecurityHooks.class); |
| } |
| |
| public static void main(String[] args) { |
| junit.textui.TestRunner.run(suite()); |
| } |
| |
| // |
| // |
| // Tests |
| // |
| // |
| |
| public void testCryptoHook() throws Exception { |
| assertNotNull("", keystore); |
| Crypto crypto = new TestCryptoImpl(keystore); |
| assertNotNull(PrivilegedAccessor.getValue(crypto, "keystore")); |
| } |
| public void testSenderLoadSignatureHook() throws Exception { |
| TestSenderImpl sender = new TestSenderImpl(); |
| // we have to coerce a value into this field or we'll get a bunch of NPEs when calling decodeSignatureParameter |
| PrivilegedAccessor.setValue(sender, "msgContext", mc); |
| PrivilegedAccessor.invokeMethod(sender, "decodeSignatureParameter", new Object[] {}); |
| assertNotNull(PrivilegedAccessor.getValue(sender, "sigCrypto")); |
| } |
| public void testSenderLoadEncryptionHook() throws Exception { |
| TestSenderImpl sender = new TestSenderImpl(); |
| // decodeEcnryptionParameter() is rather insistant on having a user (anyUser) |
| sender.setOption(WSHandlerConstants.ENCRYPTION_USER, "anyUserWillDo"); |
| // we have to coerce a value into this field or we'll get a bunch of NPEs when calling decodeSignatureParameter |
| PrivilegedAccessor.setValue(sender, "msgContext", mc); |
| PrivilegedAccessor.invokeMethod(sender, "decodeEncryptionParameter", new Object[] {}); |
| assertNotNull(PrivilegedAccessor.getValue(sender, "encCrypto")); |
| } |
| public void testReceiverLoadSignatureHook() throws Exception { |
| TestReceiverImpl receiver = new TestReceiverImpl(); |
| PrivilegedAccessor.invokeMethod(receiver, "decodeSignatureParameter", new Object[] {}); |
| assertNotNull(PrivilegedAccessor.getValue(receiver, "sigCrypto")); |
| } |
| public void testReceiverLoadDecryptionHook() throws Exception { |
| TestReceiverImpl receiver = new TestReceiverImpl(); |
| PrivilegedAccessor.invokeMethod(receiver, "decodeDecryptionParameter", new Object[] {}); |
| assertNotNull(PrivilegedAccessor.getValue(receiver, "decCrypto")); |
| } |
| |
| public void testRoundTripWithHooks() throws Exception { |
| // Setup our sender to Encrypt and Sign a soap message |
| TestSenderImpl sender = new TestSenderImpl(); |
| sender.setOption(WSHandlerConstants.ACTOR, "test"); |
| sender.setOption(WSHandlerConstants.USER, "16c73ab6-b892-458f-abf5-2f875f74882e"); |
| sender.setOption(WSHandlerConstants.ACTION, "Encrypt Signature"); |
| sender.setOption(WSHandlerConstants.SIG_KEY_ID, "DirectReference"); |
| sender.setOption(WSHandlerConstants.ENC_KEY_ID, "X509KeyIdentifier"); |
| sender.invoke(mc); |
| |
| // Make sure that at least SOMETHING happened |
| String soapPart = mc.getCurrentMessage().getSOAPPartAsString(); |
| assertNotSame("The message has not been Encrypted or Signed", soapPart, soapMessage); |
| |
| // Prepare the message context for the response |
| Message message = getSOAPMessage(soapPart); |
| mc.setPastPivot(true); |
| mc.setCurrentMessage(message); |
| |
| // Setup our receiver for the decryption / signature validation |
| TestReceiverImpl receiver = new TestReceiverImpl(); |
| receiver.setOption(WSHandlerConstants.ACTOR, "test"); |
| receiver.setOption(WSHandlerConstants.ACTION, "Encrypt Signature"); |
| receiver.invoke(mc); |
| } |
| |
| // |
| // |
| // Test Utility Classes |
| // |
| // |
| |
| /** |
| * This is a subclass of Merlin that uses the setKeyStore() method rather than the |
| * load(is) method to set the private keystore field. |
| */ |
| public class TestCryptoImpl extends BouncyCastle { |
| TestCryptoImpl(KeyStore ks) throws Exception { |
| super(null); |
| assertNotNull(ks); |
| setKeyStore(ks); |
| } |
| } |
| |
| /** |
| * Subclass of WSDoAllReceiver that creates the Crypto's directly |
| */ |
| public class TestReceiverImpl extends WSDoAllReceiver |
| { |
| protected Crypto loadDecryptionCrypto() throws AxisFault { |
| try { |
| return new TestCryptoImpl(keystore); |
| } catch(Exception e) { |
| fail("Failed to create a Crypto instance."); |
| throw new AxisFault("Failed to create a Crypto instance.", e); |
| } |
| } |
| protected Crypto loadSignatureCrypto() throws AxisFault { |
| try { |
| return new TestCryptoImpl(keystore); |
| } catch(Exception e) { |
| fail("Failed to create a Crypto instance."); |
| throw new AxisFault("Failed to create a Crypto instance.", e); |
| } |
| } |
| } |
| |
| /** |
| * Subclass of WSDoAllSender that creates the Crypto's directly |
| */ |
| public class TestSenderImpl extends WSDoAllSender |
| { |
| protected Crypto loadEncryptionCrypto() throws AxisFault { |
| try { |
| return new TestCryptoImpl(keystore); |
| } catch(Exception e) { |
| fail("Failed to create a Crypto instance."); |
| throw new AxisFault("Failed to create a Crypto instance.", e); |
| } |
| } |
| protected Crypto loadSignatureCrypto() throws AxisFault { |
| try { |
| return new TestCryptoImpl(keystore); |
| } catch(Exception e) { |
| fail("Failed to create a Crypto instance."); |
| throw new AxisFault("Failed to create a Crypto instance.", e); |
| } |
| } |
| } |
| |
| |
| // |
| // |
| // test utility methods |
| // |
| // |
| |
| protected Message getSOAPMessage(String message) throws Exception { |
| InputStream in = new ByteArrayInputStream(message.getBytes()); |
| Message msg = new Message(in); |
| msg.setMessageContext(mc); |
| return msg; |
| } |
| |
| protected KeyStore loadKeyStore() throws Exception { |
| KeyStore ks = null; |
| FileInputStream is = null; |
| is = new FileInputStream("keys/x509.PFX.MSFT"); |
| ks = KeyStore.getInstance("pkcs12"); |
| String password = "security"; |
| ks.load(is, password.toCharArray()); |
| return ks; |
| } |
| |
| public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { |
| for (int i = 0; i < callbacks.length; i++) { |
| if (callbacks[i] instanceof WSPasswordCallback) { |
| WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; |
| pc.setPassword("security"); |
| |
| } else { |
| throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); |
| } |
| } |
| } |
| |
| } |