This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new a64cd05  CXF-8015 - Support "security.signature.password" property to 
configure a signature password for WS-Security/RS-Security
a64cd05 is described below

commit a64cd0582d788064b84343012510097566f26de9
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Apr 9 11:40:31 2019 +0100

    CXF-8015 - Support "security.signature.password" property to configure a 
signature password for WS-Security/RS-Security
---
 .../cxf/rs/security/common/RSSecurityUtils.java    |  9 +--
 .../org/apache/cxf/rs/security/saml/SAMLUtils.java |  4 +-
 .../cxf/rs/security/xml/XmlSecOutInterceptor.java  |  6 +-
 .../cxf/rs/security/xml/XmlSigOutInterceptor.java  |  4 +-
 .../apache/cxf/rt/security/SecurityConstants.java  |  5 ++
 .../wss4j/AbstractWSS4JStaxInterceptor.java        | 39 +++++++++----
 .../ws/security/wss4j/SamlTokenInterceptor.java    |  4 ++
 .../cxf/ws/security/wss4j/WSS4JInInterceptor.java  | 32 +++++++++++
 .../policyhandlers/AbstractBindingBuilder.java     | 18 +++++-
 .../policyhandlers/TransportBindingHandler.java    | 13 ++++-
 .../jaxrs/security/xml/JAXRSXmlSecTest.java        | 43 ++++++++++++++
 .../ws/password/PasswordPropertiesTest.java        | 33 +++++++++++
 .../cxf/systest/ws/password/DoubleItPassword.wsdl  | 65 ++++++++++++++++++++++
 .../org/apache/cxf/systest/ws/password/server.xml  | 13 +++++
 14 files changed, 257 insertions(+), 31 deletions(-)

diff --git 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/RSSecurityUtils.java
 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/RSSecurityUtils.java
index efa4ce6..e67a0a7 100644
--- 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/RSSecurityUtils.java
+++ 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/RSSecurityUtils.java
@@ -130,14 +130,15 @@ public final class RSSecurityUtils {
         return userName;
     }
 
-    public static String getPassword(Message message, String userName,
-                                     int type, Class<?> callingClass) throws 
WSSecurityException {
+    public static String getSignaturePassword(Message message, String userName,
+                                              Class<?> callingClass) throws 
WSSecurityException {
         CallbackHandler handler = getCallbackHandler(message, callingClass);
         if (handler == null) {
-            return null;
+            // See if we have a signature password we can use here instead
+            return 
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
         }
 
-        WSPasswordCallback[] cb = {new WSPasswordCallback(userName, type)};
+        WSPasswordCallback[] cb = {new WSPasswordCallback(userName, 
WSPasswordCallback.SIGNATURE)};
         try {
             handler.handle(cb);
         } catch (Exception e) {
diff --git 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
index 52c8dd0..98aad71 100644
--- 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
+++ 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
@@ -36,7 +36,6 @@ import org.apache.cxf.rs.security.common.RSSecurityUtils;
 import org.apache.cxf.rs.security.saml.assertion.Subject;
 import org.apache.cxf.rt.security.SecurityConstants;
 import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.ext.WSPasswordCallback;
 import org.apache.wss4j.common.saml.SAMLCallback;
 import org.apache.wss4j.common.saml.SAMLUtil;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
@@ -151,8 +150,7 @@ public final class SAMLUtils {
                 }
 
                 String password =
-                    RSSecurityUtils.getPassword(message, user, 
WSPasswordCallback.SIGNATURE,
-                            SAMLUtils.class);
+                    RSSecurityUtils.getSignaturePassword(message, user, 
SAMLUtils.class);
 
                 assertion.signAssertion(user, password, crypto, false,
                                         
samlCallback.getCanonicalizationAlgorithm(),
diff --git 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSecOutInterceptor.java
 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSecOutInterceptor.java
index a035261..92d153e 100644
--- 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSecOutInterceptor.java
+++ 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSecOutInterceptor.java
@@ -50,7 +50,6 @@ import org.apache.cxf.rs.security.common.RSSecurityUtils;
 import org.apache.cxf.rt.security.SecurityConstants;
 import org.apache.cxf.rt.security.utils.SecurityUtils;
 import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.ext.WSPasswordCallback;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.util.KeyUtils;
 import org.apache.xml.security.Init;
@@ -281,8 +280,7 @@ public class XmlSecOutInterceptor extends 
AbstractPhaseInterceptor<Message> {
             throw new Exception("User name is not available");
         }
 
-        String password =
-            RSSecurityUtils.getPassword(message, user, 
WSPasswordCallback.SIGNATURE, this.getClass());
+        String password = RSSecurityUtils.getSignaturePassword(message, user, 
this.getClass());
 
         X509Certificate[] issuerCerts = 
RSSecurityUtils.getCertificates(crypto, user);
         properties.setSignatureCerts(issuerCerts);
@@ -342,7 +340,7 @@ public class XmlSecOutInterceptor extends 
AbstractPhaseInterceptor<Message> {
         if (Boolean.TRUE.equals(sigProps.getSignatureOmitC14nTransform())) {
             properties.setSignatureIncludeDigestTransform(false);
         }
-        
+
         if (elementsToSign == null || elementsToSign.isEmpty()) {
             LOG.fine("No Elements to sign are specified, so the entire request 
is signed");
             SecurePart securePart =
diff --git 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
index 7fd9a79..2e35a62 100644
--- 
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
+++ 
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
@@ -40,7 +40,6 @@ import org.apache.cxf.rs.security.common.CryptoLoader;
 import org.apache.cxf.rs.security.common.RSSecurityUtils;
 import org.apache.cxf.rt.security.SecurityConstants;
 import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.ext.WSPasswordCallback;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.xml.security.signature.XMLSignature;
 import org.apache.xml.security.transforms.Transforms;
@@ -117,8 +116,7 @@ public class XmlSigOutInterceptor extends 
AbstractXmlSecOutInterceptor {
             throw new Exception("User name is not available");
         }
 
-        String password =
-            RSSecurityUtils.getPassword(message, user, 
WSPasswordCallback.SIGNATURE, this.getClass());
+        String password = RSSecurityUtils.getSignaturePassword(message, user, 
this.getClass());
 
         X509Certificate[] issuerCerts = 
RSSecurityUtils.getCertificates(crypto, user);
 
diff --git 
a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java 
b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java
index 66b848a..5068a8f 100644
--- 
a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java
+++ 
b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java
@@ -68,6 +68,11 @@ public class SecurityConstants {
     public static final String SIGNATURE_USERNAME = 
"security.signature.username";
 
     /**
+     * The user's password for signature when a {@link CALLBACK_HANDLER} is 
not defined.
+     */
+    public static final String SIGNATURE_PASSWORD = 
"security.signature.password";
+
+    /**
      * The user's name for encryption. It is used as the alias name in the 
keystore to get the user's public
      * key for encryption. If this is not defined, then {@link USERNAME} is 
used instead. If
      * that is also not specified, it uses the the default alias set in the 
properties file referenced by
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JStaxInterceptor.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JStaxInterceptor.java
index 299efe0..96f2efd 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JStaxInterceptor.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JStaxInterceptor.java
@@ -41,6 +41,7 @@ import javax.xml.namespace.QName;
 import org.apache.cxf.binding.soap.SoapMessage;
 import org.apache.cxf.binding.soap.interceptor.SoapInterceptor;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
@@ -214,20 +215,36 @@ public abstract class AbstractWSS4JStaxInterceptor 
implements SoapInterceptor,
 
 
         // If we have a "password" but no CallbackHandler then construct one
-        if (callbackHandler == null && getPassword(soapMessage) != null) {
+        if (callbackHandler == null) {
+            final boolean outbound = MessageUtils.isOutbound(soapMessage);
             final String password = getPassword(soapMessage);
-            callbackHandler = new CallbackHandler() {
-
-                @Override
-                public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
-                    for (Callback callback : callbacks) {
-                        if (callback instanceof WSPasswordCallback) {
-                            WSPasswordCallback wsPasswordCallback = 
(WSPasswordCallback)callback;
-                            wsPasswordCallback.setPassword(password);
+            final String signatureUser =
+                
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_USERNAME,
 soapMessage);
+            final String signaturePassword =
+                
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 soapMessage);
+
+            if (!(StringUtils.isEmpty(password) && 
StringUtils.isEmpty(signaturePassword))) {
+                callbackHandler = new CallbackHandler() {
+
+                    @Override
+                    public void handle(Callback[] callbacks) throws 
IOException, UnsupportedCallbackException {
+                        for (Callback callback : callbacks) {
+                            if (callback instanceof WSPasswordCallback) {
+                                WSPasswordCallback wsPasswordCallback = 
(WSPasswordCallback)callback;
+
+                                if (signaturePassword != null && 
wsPasswordCallback.getIdentifier() != null
+                                    && 
wsPasswordCallback.getIdentifier().equals(signatureUser)
+                                    && (outbound && 
wsPasswordCallback.getUsage() == WSPasswordCallback.SIGNATURE)
+                                        || (!outbound && 
wsPasswordCallback.getUsage() == WSPasswordCallback.DECRYPT)) {
+                                    
wsPasswordCallback.setPassword(signaturePassword);
+                                } else if (password != null) {
+                                    wsPasswordCallback.setPassword(password);
+                                }
+                            }
                         }
                     }
-                }
-            };
+                };
+            }
         }
 
         if (callbackHandler != null) {
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
index fa5af24..dbcdb05 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/SamlTokenInterceptor.java
@@ -280,6 +280,10 @@ public class SamlTokenInterceptor extends 
AbstractTokenInterceptor {
                     
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.PASSWORD, 
message);
                 if (StringUtils.isEmpty(password)) {
                     password =
+                        
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
+                }
+                if (StringUtils.isEmpty(password)) {
+                    password =
                         getPassword(issuerName, token, 
WSPasswordCallback.SIGNATURE, message);
                 }
             }
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
index 14528c4..ef9958e 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.ws.security.wss4j;
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.security.Provider;
 import java.security.cert.Certificate;
@@ -28,7 +29,9 @@ import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.xml.namespace.QName;
 import javax.xml.soap.SOAPException;
 import javax.xml.soap.SOAPMessage;
@@ -50,6 +53,7 @@ import org.apache.cxf.binding.soap.saaj.SAAJUtils;
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.PropertyUtils;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.helpers.DOMUtils;
@@ -67,6 +71,7 @@ import org.apache.wss4j.common.ConfigurationConstants;
 import org.apache.wss4j.common.cache.ReplayCache;
 import org.apache.wss4j.common.crypto.Crypto;
 import org.apache.wss4j.common.crypto.ThreadLocalSecurityProvider;
+import org.apache.wss4j.common.ext.WSPasswordCallback;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.WSDataRef;
@@ -652,6 +657,33 @@ public class WSS4JInInterceptor extends 
AbstractWSS4JInterceptor {
             }
         }
 
+        // Defer to SecurityConstants.SIGNATURE_PASSWORD for decryption if no 
callback handler is defined
+        if (cbHandler == null) {
+            String signatureUser =
+                
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_USERNAME,
+                                                               
(SoapMessage)reqData.getMsgContext());
+            String password =
+                
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
+                                                       
(SoapMessage)reqData.getMsgContext());
+            if (!(StringUtils.isEmpty(signatureUser) || 
StringUtils.isEmpty(password))) {
+                cbHandler = new CallbackHandler() {
+
+                    @Override
+                    public void handle(Callback[] callbacks)
+                        throws IOException, UnsupportedCallbackException {
+                        for (Callback c : callbacks) {
+                            WSPasswordCallback pwCallback = 
(WSPasswordCallback)c;
+                            if (WSPasswordCallback.DECRYPT == 
pwCallback.getUsage()
+                                && 
signatureUser.equals(pwCallback.getIdentifier())) {
+                                pwCallback.setPassword(password);
+                            }
+                        }
+                    }
+                };
+            }
+
+        }
+
         Endpoint ep = 
((SoapMessage)reqData.getMsgContext()).getExchange().getEndpoint();
         if (ep != null && ep.getEndpointInfo() != null) {
             TokenStore store = 
TokenStoreUtils.getTokenStore((SoapMessage)reqData.getMsgContext());
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java
index 9ecc52a..945755a 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/AbstractBindingBuilder.java
@@ -590,7 +590,11 @@ public abstract class AbstractBindingBuilder extends 
AbstractCommonBindingHandle
             throw new Fault(e1);
         }
 
-        String password = getPassword(uname, token, 
WSPasswordCallback.SIGNATURE);
+        String password =
+            
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
+        if (StringUtils.isEmpty(password)) {
+            password = getPassword(uname, token, WSPasswordCallback.SIGNATURE);
+        }
         sig.setUserInfo(uname, password);
         try {
             sig.prepare(secToken.getCrypto());
@@ -946,7 +950,11 @@ public abstract class AbstractBindingBuilder extends 
AbstractCommonBindingHandle
             }
             String password = samlCallback.getIssuerKeyPassword();
             if (password == null) {
-                password = getPassword(issuerName, token, 
WSPasswordCallback.SIGNATURE);
+                password =
+                    
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
+                if (StringUtils.isEmpty(password)) {
+                    password = getPassword(issuerName, token, 
WSPasswordCallback.SIGNATURE);
+                }
             }
             Crypto crypto = samlCallback.getIssuerCrypto();
             if (crypto == null) {
@@ -1883,7 +1891,11 @@ public abstract class AbstractBindingBuilder extends 
AbstractCommonBindingHandle
             }
         }
 
-        String password = getPassword(user, token, 
WSPasswordCallback.SIGNATURE);
+        String password =
+            
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
+        if (StringUtils.isEmpty(password)) {
+            password = getPassword(user, token, WSPasswordCallback.SIGNATURE);
+        }
         sig.setUserInfo(user, password);
         
sig.setSignatureAlgorithm(binding.getAlgorithmSuite().getAsymmetricSignature());
         AlgorithmSuiteType algType = 
binding.getAlgorithmSuite().getAlgorithmSuiteType();
diff --git 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
index b9d34c9..3a1b7c4 100644
--- 
a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
+++ 
b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/policyhandlers/TransportBindingHandler.java
@@ -32,6 +32,7 @@ import javax.xml.soap.SOAPMessage;
 import org.w3c.dom.Element;
 
 import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.rt.security.utils.SecurityUtils;
@@ -378,7 +379,7 @@ public class TransportBindingHandler extends 
AbstractBindingBuilder {
             dkSig.setStoreBytesInAttachment(storeBytesInAttachment);
             dkSig.setExpandXopInclude(isExpandXopInclude());
             dkSig.setWsDocInfo(wsDocInfo);
-            
+
             AlgorithmSuiteType algType = 
binding.getAlgorithmSuite().getAlgorithmSuiteType();
             dkSig.setDerivedKeyLength(algType.getSignatureDerivedKeyLength() / 
8);
 
@@ -465,7 +466,7 @@ public class TransportBindingHandler extends 
AbstractBindingBuilder {
         dkSign.setStoreBytesInAttachment(storeBytesInAttachment);
         dkSign.setExpandXopInclude(isExpandXopInclude());
         dkSign.setWsDocInfo(wsDocInfo);
-        
+
         AlgorithmSuite algorithmSuite = tbinding.getAlgorithmSuite();
 
         //Setting the AttachedReference or the UnattachedReference according 
to the flag
@@ -585,7 +586,13 @@ public class TransportBindingHandler extends 
AbstractBindingBuilder {
                 String userNameKey = SecurityConstants.SIGNATURE_USERNAME;
                 uname = 
(String)SecurityUtils.getSecurityPropertyValue(userNameKey, message);
             }
-            String password = getPassword(uname, token, 
WSPasswordCallback.SIGNATURE);
+
+            String password =
+                
(String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SIGNATURE_PASSWORD,
 message);
+            if (StringUtils.isEmpty(password)) {
+                password = getPassword(uname, token, 
WSPasswordCallback.SIGNATURE);
+            }
+
             sig.setUserInfo(uname, password);
             
sig.setSignatureAlgorithm(binding.getAlgorithmSuite().getAsymmetricSignature());
         } else {
diff --git 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
index 5d59e8b..07db942 100644
--- 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
+++ 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
@@ -805,6 +805,49 @@ public class JAXRSXmlSecTest extends 
AbstractBusClientServerTestBase {
         }
     }
 
+    @Test
+    public void testSignaturePassword() throws Exception {
+        String address = "https://localhost:"; + test.port + 
"/xmlsig/bookstore/books";
+
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setAddress(address);
+
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = JAXRSXmlSecTest.class.getResource("client.xml");
+        Bus springBus = bf.createBus(busFile.toString());
+        bean.setBus(springBus);
+
+        Map<String, Object> properties = new HashMap<>();
+        properties.put(SecurityConstants.SIGNATURE_USERNAME, "alice");
+        properties.put(SecurityConstants.SIGNATURE_PASSWORD, "password");
+        properties.put(SecurityConstants.SIGNATURE_PROPERTIES,
+                       
"org/apache/cxf/systest/jaxrs/security/alice.properties");
+        bean.setProperties(properties);
+        if (test.streaming) {
+            XmlSecOutInterceptor sigOutInterceptor = new 
XmlSecOutInterceptor();
+            sigOutInterceptor.setSignRequest(true);
+            sigOutInterceptor.setKeyInfoMustBeAvailable(true);
+            bean.getOutInterceptors().add(sigOutInterceptor);
+
+            XmlSecInInterceptor sigInInterceptor = new XmlSecInInterceptor();
+            sigInInterceptor.setRequireSignature(true);
+            bean.setProvider(sigInInterceptor);
+        } else {
+            XmlSigOutInterceptor sigOutInterceptor = new 
XmlSigOutInterceptor();
+            sigOutInterceptor.setKeyInfoMustBeAvailable(true);
+            bean.getOutInterceptors().add(sigOutInterceptor);
+
+            XmlSigInInterceptor sigInInterceptor = new XmlSigInInterceptor();
+            sigInInterceptor.setKeyInfoMustBeAvailable(true);
+            bean.getInInterceptors().add(sigInInterceptor);
+        }
+
+        WebClient wc = bean.createWebClient();
+        
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000L);
+        Book book = wc.type("application/xml").post(new Book("CXF", 126L), 
Book.class);
+        assertEquals(126L, book.getId());
+    }
+
     private static final class TestParam {
         final String port;
         final boolean streaming;
diff --git 
a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/password/PasswordPropertiesTest.java
 
b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/password/PasswordPropertiesTest.java
index 31ef815..fd68f33 100644
--- 
a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/password/PasswordPropertiesTest.java
+++ 
b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/password/PasswordPropertiesTest.java
@@ -148,4 +148,37 @@ public class PasswordPropertiesTest extends 
AbstractBusClientServerTestBase {
         bus.shutdown(true);
     }
 
+    @org.junit.Test
+    public void testAsymmetricBinding() throws Exception {
+
+        SpringBusFactory bf = new SpringBusFactory();
+
+        Bus bus = bf.createBus();
+        BusFactory.setDefaultBus(bus);
+        BusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = 
PasswordPropertiesTest.class.getResource("DoubleItPassword.wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItAsymmetricPort");
+
+        DoubleItPortType port =
+                service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(port, PORT);
+
+        if (test.isStreaming()) {
+            SecurityTestUtil.enableStreaming(port);
+        }
+
+        Client client = ClientProxy.getClient(port);
+        client.getRequestContext().put(SecurityConstants.SIGNATURE_USERNAME, 
"alice");
+        client.getRequestContext().put(SecurityConstants.SIGNATURE_PROPERTIES, 
"alice.properties");
+        client.getRequestContext().put(SecurityConstants.SIGNATURE_PASSWORD, 
"password");
+        client.getRequestContext().put(SecurityConstants.ENCRYPT_USERNAME, 
"bob");
+        client.getRequestContext().put(SecurityConstants.ENCRYPT_PROPERTIES, 
"bob.properties");
+
+        assertEquals(50, port.doubleIt(25));
+
+        ((java.io.Closeable)port).close();
+        bus.shutdown(true);
+    }
 }
diff --git 
a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/DoubleItPassword.wsdl
 
b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/DoubleItPassword.wsdl
index 03b2bcb..3425ca8 100644
--- 
a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/DoubleItPassword.wsdl
+++ 
b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/DoubleItPassword.wsdl
@@ -51,6 +51,22 @@
             </wsdl:fault>
         </wsdl:operation>
     </wsdl:binding>
+    <wsdl:binding name="DoubleItAsymmetricBinding" type="tns:DoubleItPortType">
+        <wsp:PolicyReference URI="#DoubleItAsymmetricPolicy"/>
+        <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="DoubleIt">
+            <soap:operation soapAction=""/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+            <wsdl:fault name="DoubleItFault">
+                <soap:body use="literal" name="DoubleItFault"/>
+            </wsdl:fault>
+        </wsdl:operation>
+    </wsdl:binding>
     
     <wsdl:service name="DoubleItService">
         <wsdl:port name="DoubleItUTPort" binding="tns:DoubleItUTBinding">
@@ -59,6 +75,9 @@
         <wsdl:port name="DoubleItUTSignedPort" 
binding="tns:DoubleItUTSignedBinding">
             <soap:address location="http://localhost:9001/DoubleItUTSigned"/>
         </wsdl:port>
+        <wsdl:port name="DoubleItAsymmetricPort" 
binding="tns:DoubleItAsymmetricBinding">
+            <soap:address location="http://localhost:9001/DoubleItAsymmetric"/>
+        </wsdl:port>
     </wsdl:service>
     
     <wsp:Policy wsu:Id="DoubleItUTSupportingPolicy">
@@ -125,5 +144,51 @@
             </wsp:All>
         </wsp:ExactlyOne>
     </wsp:Policy>
+    <wsp:Policy wsu:Id="DoubleItAsymmetricPolicy">
+        <wsp:ExactlyOne>
+            <wsp:All>
+                <sp:AsymmetricBinding>
+                    <wsp:Policy>
+                        <sp:InitiatorToken>
+                            <wsp:Policy>
+                                <sp:X509Token 
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient";>
+                                    <wsp:Policy>
+                                        <sp:WssX509V3Token10/>
+                                    </wsp:Policy>
+                                </sp:X509Token>
+                            </wsp:Policy>
+                        </sp:InitiatorToken>
+                        <sp:RecipientToken>
+                            <wsp:Policy>
+                                <sp:X509Token 
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never";>
+                                    <wsp:Policy>
+                                        <sp:WssX509V3Token10/>
+                                    </wsp:Policy>
+                                </sp:X509Token>
+                            </wsp:Policy>
+                        </sp:RecipientToken>
+                        <sp:Layout>
+                            <wsp:Policy>
+                                <sp:Lax/>
+                            </wsp:Policy>
+                        </sp:Layout>
+                        <sp:IncludeTimestamp/>
+                        <sp:OnlySignEntireHeadersAndBody/>
+                        <sp:AlgorithmSuite>
+                            <wsp:Policy>
+                                <sp:Basic128/>
+                            </wsp:Policy>
+                        </sp:AlgorithmSuite>
+                    </wsp:Policy>
+                </sp:AsymmetricBinding>
+                <sp:EncryptedParts>
+                    <sp:Body/>
+                </sp:EncryptedParts>
+                <sp:SignedParts>
+                    <sp:Body/>
+                </sp:SignedParts>
+            </wsp:All>
+        </wsp:ExactlyOne>
+    </wsp:Policy>
     
 </wsdl:definitions>
diff --git 
a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/server.xml
 
b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/server.xml
index 86ec297..8d4268b 100644
--- 
a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/server.xml
+++ 
b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/password/server.xml
@@ -54,5 +54,18 @@
         </jaxws:properties>
     </jaxws:endpoint>
     
+    <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt"; 
id="Asymmetric" 
+        
address="http://localhost:${testutil.ports.password.Server}/DoubleItAsymmetric"; 
serviceName="s:DoubleItService" 
+        endpointName="s:DoubleItAsymmetricPort" 
implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" 
+        
wsdlLocation="org/apache/cxf/systest/ws/password/DoubleItPassword.wsdl">
+        <jaxws:properties>
+            <entry key="security.signature.username" value="bob"/>
+            <entry key="security.signature.password" value="password"/>
+            <entry key="security.signature.properties" value="bob.properties"/>
+            <entry key="security.encryption.properties" 
value="alice.properties"/>
+            <entry key="security.encryption.username" value="alice"/>
+        </jaxws:properties>
+    </jaxws:endpoint>
+    
 
 </beans>
\ No newline at end of file

Reply via email to