CXF 2.3.1 is truely ancient. Please upgrade to a more recent (and supported) version of CXF. It would help a lot in diagnosing the problem if you were to include the request that is failing, along with the service configuration + the stacktrace.
At a guess the client is either not using the correct public key for the service (are you specifying the service alias via "encryptionUser"?), or else the wrong password is being supplied on the inbound side via the CallbackHandler or the properties file. Colm. On Thu, Apr 18, 2013 at 1:27 AM, Andrew Hart <[email protected]> wrote: > I am using JBoss AS 6.1 with CXF 2.3.1 bundled and I believe the version > of WSS4J included in that is 1.5.8. My version of the JDK is 1.6. > > I have been struggling for several days now to get a simple test going > using SOAPUi 4.5.1 as the client. I have reviewed the WS-Security spec, > looked at numerous tutorials, including the documentation on the CXF > website and Mr. Mazza's blog describing the process. I cannot be sure > whether the problem is SOAPUi or my service. In any case, I am sort of > constrained to use this old version of JBoss AS along with it's old > versions of CXF and WSS4j, so many of the features described on the CXF > tutorial are not applicable, I believe, for example the > DefaultCryptoCoverageChecker. I think I would prefer to use the > interceptors rather than the WS-Policy as I am not using the WSDL first > method. I have not tried the WS-Policy annotations. > > I have a server.keystore which contains the public/private key pair for > the server. Into this I have also imported the client certs for two > test clients, client1 and client2. > So, I have the inverse, a client1.keystore with client1 public/private > keys and the server public key certificate is imported into this file. > Likewise for client2. The aliases for these are server, client1, and > client2, respectively. The passwords for all the keystores and aliases > is currently just "password". > > > First, here is an excerpt of my service implementation: > > @WebService(serviceName = "My_Web_Service", name = "MyWebService", > targetNamespace = "http://mycompany.com") > @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = > SOAPBinding.Use.LITERAL, parameterStyle = > SOAPBinding.ParameterStyle.WRAPPED) > //@EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml", > configName = "Standard WSSecurity Endpoint") > public class MyWebService { > > private static Log log = LogFactory.getLog(MyWebService.class); > > /** > * Returns the list of Area of Operation codes. > * > * @return List<AreaOfOperationsBean> > */ > @WebMethod() > @WebResult(name = "payLoad") > public PayLoad getAreaOfOperationsData() > > { > log.debug("Req method: getCipAreaOfOperationsData!"); > > [... setup the payload object deleted] > return p; > > } // getAreaOfOperationsData() > > [...] > } > > Configuration of the WSS4J interceptors is done using the > jbossws-cxf.xml file which is in the WEB-INF directory of my service > WAR: > > > <beans > xmlns='http://www.springframework.org/schema/beans' > xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' > xmlns:beans='http://www.springframework.org/schema/beans' > xmlns:jaxws='http://cxf.apache.org/jaxws' > xsi:schemaLocation='http://cxf.apache.org/core > http://cxf.apache.org/schemas/core.xsd > http://www.springframework.org/schema/beans > http://www.springframework.org/schema/beans/spring-beans-2.0.xsd > http://cxf.apache.org/jaxws > http://cxf.apache.org/schemas/jaxws.xsd'> > > > <bean id="Sign_Request" > class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> > <constructor-arg> > <map> > <entry key="action" value="Timestamp Signature"/> > <entry key="signaturePropFile" value="security.properties"/> > <entry key="decryptionPropFile" value="security.properties"/> > <entry key="passwordCallbackClass" > value="com.mycompany.ws.common.KeystorePasswordCallback"/> > </map> > </constructor-arg> > </bean> > > > <bean id="Sign_Response" > class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> > <constructor-arg> > <map> > <entry key="action" value="Timestamp Signature Encrypt"/> > <entry key="user" value="server "/> > <entry key="signaturePropFile" value="security.properties"/> > <entry key="encryptionPropFile" value="security.properties"/> > <!-- <entry key="encryptionUser" value="useReqSigCert"/> --> > <entry key="encryptionUser" value="client1 " /> > <entry key="signatureKeyIdentifier" value="DirectReference"/> > <entry key="encryptionKeyIdentifier" value="DirectReference" /> > <entry key="passwordCallbackClass" > value="com.mycompany.ws.common.KeystorePasswordCallback"/> > <entry key="signatureParts" > value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss > -wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.o > rg/soap/envelope/}Body"/> > <entry key="encryptionParts" > value="{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{ > http://schemas.xmlsoap.org/soap/envelope/}Body"/> > <entry key="encryptionKeyTransportAlgorithm" > value="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> > <entry key="encryptionSymAlgorithm" > value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/> > </map> > </constructor-arg> > </bean> > > <jaxws:endpoint > id='CipService' > address='http://@jboss.bind.address@:8080/ws-cip' > implementor='com.mycompany.ws.MyService'> > <jaxws:invoker> > <bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/> > </jaxws:invoker> > <jaxws:outInterceptors> > <bean > class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/> > <ref bean="Sign_Response"/> > </jaxws:outInterceptors> > > <jaxws:inInterceptors> > <ref bean="Sign_Request"/> > <bean > class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/> > </jaxws:inInterceptors> > > </jaxws:endpoint> > </beans> > > You'll note that I have encryptionUser = useReqSigCert commented out at > the moment because I haven't been able to get it working, so I'm trying > to just hardcode the client alias, but alas, that isn't working either > as you will see. > > My password callback handler is simple: > > package com.mycompany.ws.common; > > import java.io.IOException; > import java.util.HashMap; > import java.util.Map; > > import javax.security.auth.callback.Callback; > import javax.security.auth.callback.CallbackHandler; > import javax.security.auth.callback.UnsupportedCallbackException; > > import org.apache.log4j.Logger; > import org.apache.ws.security.WSPasswordCallback; > > public class KeystorePasswordCallback implements CallbackHandler { > > private static Logger log = Logger > .getLogger(KeystorePasswordCallback.class); > private Map<String, String> passwords = new HashMap<String, > String>(); > > public KeystorePasswordCallback() { > log.info("Creating ws security callback handler..."); > passwords.put("server ", "password"); > passwords.put("client1 ", "password"); > passwords.put("client2 ", "password"); > } > > public void handle(Callback[] callbacks) throws IOException, > UnsupportedCallbackException { > log.info("KeystorePasswordCallback invoked handle"); > for (int i = 0; i < callbacks.length; i++) { > WSPasswordCallback pc = (WSPasswordCallback) > callbacks[i]; > String id = pc.getIdentifier(); > log.info("Looking up password for identifier: " > + id); > String pass = passwords.get(pc.getIdentifier()); > if (pass != null) { > pc.setPassword(pass); > return; > } > } > } > > public void setAliasPassword(String alias, String password) { > passwords.put(alias, password); > } > } > > > My security.properties file is located in the WEB-INF directory (since > my service is a POJO): > > org.apache.ws.security.crypto.provider=org.apache.ws.security.components > .crypto.Merlin > org.apache.ws.security.crypto.merlin.keystore.type=jks > org.apache.ws.security.crypto.merlin.keystore.password=password > org.apache.ws.security.crypto.merlin.keystore.alias=server > org.apache.ws.security.crypto.merlin.file=server.keystore > > > Since I have the client certs with their public keys in there, I don't > think I need a separate truststore. > > OK, so that's all of the server side. My goal is to test this using > soapUi version 4.5.1. This version of soapUi is using an embedded Java > JRE 1.7 if that makes a difference. > I hope someone is familiar with it, but basically, under my project > configuration I have defined the two client keystores, client1.keystore > and client2.keystore and entered their password. > My "incoming" WS-Security configuration is simple; there isn't much to > configure there: I have specified the decrypt and signature keystores > as client1.keystore and included the password. > > For the "outgoing" WS-Security configuration, I currently have a default > Username/alias of "client1", the default password of "password", no > actor specified, and "Must Understand" is not checked. For the > actions: > > "Timestamp" with a TTL of 1800000 and millisecond precision. > > "Signature" with > Keystore = client1.keystore > Alias = client1 > Password = password > Key Identifier Type: [options are "Issurer Name and Serial > Number", "Binary Security Token", "X509 Certificate", and "Subject Key > Identifier"]. I have tried all of them and my current setting is > "Binary Security Token". (In the WS-Security spec it said an X.509 cert > was an example of such) > Signature Algorithm is: > http://www.w3.org/2000/09/xmldsig#rsa-sha1 > Signature Canonicalization is: > http://www.w3.org/2001/10/xml-exc-c14n# > Digest Algorithm is: http://www.w3.org/2000/09/xmldsig#sha1 > Use Single Certificate: true > I currently do not have any Parts specified. I think this may > be incorrect, or at least not recommended. > > > OK, so when I create a request in SoapUi and attach the "outgoing" > ws-security stuff and send it to the server, I see this in the console: > > 17:44:10,348 INFO [com.mycompany.ws.common.KeystorePasswordCallback] > Creating ws security callback handler... > 17:44:10,348 INFO [com. mycompany.ws.common.KeystorePasswordCallback] > KeystorePasswordCallback invoked handle > 17:44:10,348 INFO [com. mycompany.ws.common.KeystorePasswordCallback] > Looking up password for identifier: server > > And, then, in the soapUi error log, I see this stack trace: > > Wed Apr 17 17:44:10 CDT > 2013:ERROR:org.apache.ws.security.WSSecurityException: The signature or > decryption was invalid > org.apache.ws.security.WSSecurityException: The signature or > decryption was invalid > at > org.apache.ws.security.processor.EncryptedKeyProcessor.handleToken(Encry > ptedKeyProcessor.java:106) > at > org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity > Engine.java:396) > at > org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity > Engine.java:304) > at > org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity > Engine.java:249) > at > com.eviware.soapui.impl.wsdl.support.wss.IncomingWss.processIncoming(Inc > omingWss.java:121) > at > com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments. > WsdlSinglePartHttpResponse.processIncomingWss(WsdlSinglePartHttpResponse > .java:49) > at > com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments. > WsdlSinglePartHttpResponse.<init>(WsdlSinglePartHttpResponse.java:38) > at > com.eviware.soapui.impl.wsdl.submit.filters.HttpPackagingResponseFilter. > wsdlRequest(HttpPackagingResponseFilter.java:71) > at > com.eviware.soapui.impl.wsdl.submit.filters.HttpPackagingResponseFilter. > afterAbstractHttpResponse(HttpPackagingResponseFilter.java:48) > at > com.eviware.soapui.impl.wsdl.submit.filters.AbstractRequestFilter.afterR > equest(AbstractRequestFilter.java:64) > at > com.eviware.soapui.impl.wsdl.submit.transports.http.HttpClientRequestTra > nsport.sendRequest(HttpClientRequestTransport.java:297) > at > com.eviware.soapui.impl.wsdl.WsdlSubmit.run(WsdlSubmit.java:123) > at java.util.concurrent.Executors$RunnableAdapter.call(Unknown > Source) > at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) > at java.util.concurrent.FutureTask.run(Unknown Source) > at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown > Source) > at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown > Source) > at java.lang.Thread.run(Unknown Source) > Caused by: org.apache.ws.security.WSSecurityException: General > security error (The private key for the supplied alias does not exist in > the keystore) > at > org.apache.ws.security.components.crypto.Merlin.getPrivateKey(Merlin.jav > a:661) > at > org.apache.ws.security.processor.EncryptedKeyProcessor.handleToken(Encry > ptedKeyProcessor.java:103) > ... 17 more > Caused by: java.security.UnrecoverableKeyException: Cannot recover > key > at sun.security.provider.KeyProtector.recover(Unknown Source) > at sun.security.provider.JavaKeyStore.engineGetKey(Unknown > Source) > at sun.security.provider.JavaKeyStore$JKS.engineGetKey(Unknown > Source) > at java.security.KeyStore.getKey(Unknown Source) > at > org.apache.ws.security.components.crypto.Merlin.getPrivateKey(Merlin.jav > a:647) > ... 18 more > > > But, I know that the alias DOES exist in the keystore. I was confused > by the fact that the PasswordCallbackhandler is looking up the password > for "server", so I tried putting "client1" in there instead of " > useReqSigCert" for that reason, but the result is the same. I read > somewhere on a JBoss forum something about useReqSigCert not working > correctly unless the request was also encrypted, so I have tried also > encrypting the request from SoapUi. > > When encrypting from the client, I add a third action "Encryption" using > the following settings: > Keystore = client1.keystore > Alias = server > Password = "password" > Key Identifier Type = "Binary Security Token" [ in addition to the > options for signing, it also adds "Embedded KeyInfo", "Embed Security > Token Reference", and "Thumbprint SHA1 Identifier". Again, I've tried > them all with the exception of Embedded Key Info because I am unclear > what to enter for "Embedded KeyName" and "Embedded Key Password" > > Embedded Keyname = blank > Embedded Key Password = blank > Symmetric Encoding Algorithm = > http://www.w3.org/2001/04/xmlenc#tripledes-cbc > Key Encryption Algorithm = http://www.w2.org/2001/04/xmlenc#rsa-1_5 > Create Encrypted Key = checked. (I've tried it both ways) > Parts = blank. (My understanding is that when parts are blank, the > entire SOAP message is signed or encrypted. Again, perhaps not > recommended?) > > When I do that, I get an error on the server: > org.apache.cxf.interceptor.Fault: Message part > {http://www.w3.org/2001/04/xmlenc#}EncryptedData was not recognized. > (Does it exist in service WSDL?) > > Ok, so I uncheck the "Create Encrypted Key" and try again and I get: > 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback] > Creating Akimeka ws security callback handler... > 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback] > KeystorePasswordCallback invoked handle > 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback] > Looking up password for identifier: null > 19:06:57,547 WARN [org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor] > : org.apache.ws.security.WSSecurityException: The signature or > decryption was invalid (Unsupported key identification) > > I switch to Key Identifier = "X509 Certificate" I get the same error. > I switch to "Issuer Name and Serial", same error. "Embedded KeyInfo" > gets me an "actions mismatch" error on the server. > > And, so you get the drift: I'm basically a chimp with a keyboard here, > trying to stumble upon a Shakespearean sonnet. I have no idea what the > correct settings should be. (Although I swear I have some dim > recollection of getting client to server decrypting working at some > point over the past several days.) > > So... I feel like what I want to do should be very simple, but I'm not > sure how to proceed at this point. I may be dealing with problems with > SoapUi, with this old version of CXF/WSS4j/Jboss, or just plain > ignorance, but I sure could use some help. > > Sorry for the long mail, thanks in advance. > > > > > > > > > > NOTICE: This transmission (including all attachments) is company > confidential, is intended only for the individual or entity named above, > and is likely to contain privileged, proprietary and confidential > information that is exempt from disclosure requests under applicable law. > If you are not the intended recipient, you are hereby notified that any > disclosure, copying, distribution, use of or reliance upon any of the > information contained in this transmission is strictly prohibited. Any > inadvertent or unauthorized disclosure shall not compromise or waive the > confidentiality of this transmission. If you have received this > transmission in error, please forward this message immediately to > [email protected] <mailto:[email protected]> and delete or > otherwise remove this email from your system. Thank you > > -- Colm O hEigeartaigh Talend Community Coder http://coders.talend.com
