Details
-
Improvement
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
2.6.1, 2.7
-
None
-
Unknown
Description
Given a WS-Security configuration like here: http://tinyurl.com/bv2qpe4 except using different properties files for encryption and signature. If I fail to provide the keystore password for the signature properties file (http://tinyurl.com/cxdjngu) the CXF exception helpfully tells me there's a credential/password problem:
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
at $Proxy25.doubleIt(Unknown Source)
at client.WSClient.doubleIt(WSClient.java:27)
at client.WSClient.main(WSClient.java:21)
Caused by: org.apache.ws.security.WSSecurityException: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.ws.security.components.crypto.CryptoFactory.loadClass(CryptoFactory.java:224)
at org.apache.ws.security.components.crypto.CryptoFactory.getInstance(CryptoFactory.java:117)
at org.apache.ws.security.components.crypto.CryptoFactory.getInstance(CryptoFactory.java:78)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getCrypto(AbstractBindingBuilder.java:1530)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureCrypto(AbstractBindingBuilder.java:1437)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureBuilder(AbstractBindingBuilder.java:1774)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignature(AsymmetricBindingHandler.java:540)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:146)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:97)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:165)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:89)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
... 3 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.apache.ws.security.components.crypto.CryptoFactory.loadClass(CryptoFactory.java:219)
... 20 more
Caused by: org.apache.ws.security.components.crypto.CredentialException: Failed to load credentials.
at org.apache.ws.security.components.crypto.Merlin.load(Merlin.java:371)
at org.apache.ws.security.components.crypto.Merlin.loadProperties(Merlin.java:190)
at org.apache.ws.security.components.crypto.Merlin.<init>(Merlin.java:140)
... 25 more
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:772)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1214)
at org.apache.ws.security.components.crypto.Merlin.load(Merlin.java:365)
... 27 more
Caused by: java.security.UnrecoverableKeyException: Password verification failed
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:770)
... 30 more
But when I fail to provide the keystore password for the encryption properties file, it just tells me it couldn't create a Crypto object:
org.apache.cxf.interceptor.Fault: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:194)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:97)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:165)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:89)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
at $Proxy25.doubleIt(Unknown Source)
at client.WSClient.doubleIt(WSClient.java:27)
at client.WSClient.main(WSClient.java:21)
Caused by: org.apache.cxf.ws.policy.PolicyException: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.policyNotAsserted(AbstractBindingBuilder.java:307)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doEncryption(AsymmetricBindingHandler.java:435)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:189)
... 13 more
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
at $Proxy25.doubleIt(Unknown Source)
at client.WSClient.doubleIt(WSClient.java:27)
at client.WSClient.main(WSClient.java:21)
Caused by: org.apache.cxf.ws.policy.PolicyException: class org.apache.ws.security.components.crypto.Merlin cannot create instance
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.policyNotAsserted(AbstractBindingBuilder.java:307)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doEncryption(AsymmetricBindingHandler.java:435)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:189)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:97)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:165)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:89)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
I debugged it and the exception handling for encryption and signatures is different. For both signature and encryption, the problem is trapped in Merlin.load(InputStream input, String storepass, String provider, String type)--line 368, which throws a CredentialException. For signature, CryptoFactory.loadClass() throws a WSSecurityException instead, and from that, AsymmetricBindingHandler.doSignBeforeEncrypt()'s exception handler does "throw new Fault(e)", allowing the CredentialException to be shown to the user. But for encryption, it is handled in method PolicyNotAsserted (line 292 of AbstractBindingBuilder, called from AsymmetricBindingHandler.doEncryption(), line 441), causing the CredentialException to be lost.
As an added bonus, if the "failed credentials" message could be given more succinctly than a long error trace that would be good but that can be looked at a later date.
The source code linked to above and described in this blog: http://www.jroller.com/gmazza/entry/cxf_x509_profile_secpol can be used as a test case, just create a separate properties file for the encryption keystore with a missing keystore password.