You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/12/23 18:30:03 UTC

svn commit: r1553156 - in /cxf/trunk: rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/ rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/ rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml...

Author: sergeyb
Date: Mon Dec 23 17:30:03 2013
New Revision: 1553156

URL: http://svn.apache.org/r1553156
Log:
[CXF-5424] Optionally loading the key info out of band

Modified:
    cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
    cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
    cxf/trunk/rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/SAMLResponseValidatorTest.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/AbstractXmlSigInHandler.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/server.xml

Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java (original)
+++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java Mon Dec 23 17:30:03 2013
@@ -73,6 +73,7 @@ public class RequestAssertionConsumerSer
     private boolean supportBase64Encoding = true;
     private boolean enforceAssertionsSigned = true;
     private boolean enforceKnownIssuer = true;
+    private boolean keyInfoMustBeAvailable = true;
     private TokenReplayCache<String> replayCache;
 
     private MessageContext messageContext;
@@ -281,6 +282,7 @@ public class RequestAssertionConsumerSer
     ) {
         try {
             SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator();
+            protocolValidator.setKeyInfoMustBeAvailable(keyInfoMustBeAvailable);
             protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), getCallbackHandler());
         } catch (WSSecurityException ex) {
             LOG.log(Level.FINE, ex.getMessage(), ex);
@@ -338,4 +340,7 @@ public class RequestAssertionConsumerSer
         LOG.warning(errorMsg.toString());
     }
     
+    public void setKeyInfoMustBeAvailable(boolean keyInfoMustBeAvailable) {
+        this.keyInfoMustBeAvailable = keyInfoMustBeAvailable;
+    }
 }

Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java (original)
+++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLProtocolResponseValidator.java Mon Dec 23 17:30:03 2013
@@ -81,7 +81,7 @@ public class SAMLProtocolResponseValidat
     
     private Validator assertionValidator = new SamlAssertionValidator();
     private Validator signatureValidator = new SignatureTrustValidator();
-    
+    private boolean keyInfoMustBeAvailable = true;
     /**
      * Validate a SAML 2 Protocol Response
      * @param samlResponse
@@ -256,16 +256,21 @@ public class SAMLProtocolResponseValidat
         requestData.setWssConfig(wssConfig);
         requestData.setCallbackHandler(callbackHandler);
         
-        KeyInfo keyInfo = signature.getKeyInfo();
         SAMLKeyInfo samlKeyInfo = null;
-        try {
-            samlKeyInfo = 
-                SAMLUtil.getCredentialFromKeyInfo(
-                    keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)), sigCrypto
-                );
-        } catch (WSSecurityException ex) {
-            LOG.log(Level.FINE, "Error in getting KeyInfo from SAML Response: " + ex.getMessage(), ex);
-            throw ex;
+        
+        KeyInfo keyInfo = signature.getKeyInfo();
+        if (keyInfo != null) {
+            try {
+                samlKeyInfo = 
+                    SAMLUtil.getCredentialFromKeyInfo(
+                        keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)), sigCrypto
+                    );
+            } catch (WSSecurityException ex) {
+                LOG.log(Level.FINE, "Error in getting KeyInfo from SAML Response: " + ex.getMessage(), ex);
+                throw ex;
+            }
+        } else if (!keyInfoMustBeAvailable) {
+            samlKeyInfo = createKeyInfoFromDefaultAlias(sigCrypto);
         }
         if (samlKeyInfo == null) {
             LOG.fine("No KeyInfo supplied in the SAMLResponse signature");
@@ -288,6 +293,19 @@ public class SAMLProtocolResponseValidat
         }
     }
     
+    protected SAMLKeyInfo createKeyInfoFromDefaultAlias(Crypto sigCrypto) throws WSSecurityException {
+        try {
+            X509Certificate[] certs = SecurityUtils.getCertificates(sigCrypto, 
+                                                                    sigCrypto.getDefaultX509Identifier());
+            SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(new X509Certificate[]{certs[0]});
+            samlKeyInfo.setPublicKey(certs[0].getPublicKey());
+            return samlKeyInfo;
+        } catch (Exception ex) {
+            LOG.log(Level.FINE, "Error in loading the certificates: " + ex.getMessage(), ex);
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex);
+        }
+    }
+    
     /**
      * Validate a signature against the profiles
      */
@@ -351,12 +369,23 @@ public class SAMLProtocolResponseValidat
             try {
                 Signature sig = assertion.getSignature();
                 WSDocInfo docInfo = new WSDocInfo(sig.getDOM().getOwnerDocument());
-                KeyInfo keyInfo = sig.getKeyInfo();
                 
-                SAMLKeyInfo samlKeyInfo = 
-                    SAMLUtil.getCredentialFromKeyInfo(
+                SAMLKeyInfo samlKeyInfo = null;
+                
+                KeyInfo keyInfo = sig.getKeyInfo();
+                if (keyInfo != null) {
+                    samlKeyInfo = SAMLUtil.getCredentialFromKeyInfo(
                         keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, docInfo), sigCrypto
                     );
+                } else if (!keyInfoMustBeAvailable) {
+                    samlKeyInfo = createKeyInfoFromDefaultAlias(sigCrypto);
+                }
+
+                if (samlKeyInfo == null) {
+                    LOG.fine("No KeyInfo supplied in the SAMLResponse assertion signature");
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+                }
+                
                 assertion.verifySignature(samlKeyInfo);
                 
                 assertion.parseHOKSubject(
@@ -519,4 +548,8 @@ public class SAMLProtocolResponseValidat
         }
     }
 
+    public void setKeyInfoMustBeAvailable(boolean keyInfoMustBeAvailable) {
+        this.keyInfoMustBeAvailable = keyInfoMustBeAvailable;
+    }
+
 }

Modified: cxf/trunk/rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/SAMLResponseValidatorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/SAMLResponseValidatorTest.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/SAMLResponseValidatorTest.java (original)
+++ cxf/trunk/rt/rs/security/sso/saml/src/test/java/org/apache/cxf/rs/security/saml/sso/SAMLResponseValidatorTest.java Mon Dec 23 17:30:03 2013
@@ -235,7 +235,7 @@ public class SAMLResponseValidatorTest e
         ((Merlin)issuerCrypto).setKeyStore(keyStore);
         
         response.getAssertions().add(assertion.getSaml2());
-        signResponse(response, "alice", "password", issuerCrypto);
+        signResponse(response, "alice", "password", issuerCrypto, true);
         
         Element policyElement = OpenSAMLUtil.toDom(response, doc);
         doc.appendChild(policyElement);
@@ -257,6 +257,64 @@ public class SAMLResponseValidatorTest e
             marshalledResponse, issuerCrypto, new KeystorePasswordCallback()
         );
     }
+    
+    @org.junit.Test
+    public void testSignedResponseNoKeyInfo() throws Exception {
+        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+        
+        Status status = 
+            SAML2PResponseComponentBuilder.createStatus(
+                SAMLProtocolResponseValidator.SAML2_STATUSCODE_SUCCESS, null
+            );
+        Response response = 
+            SAML2PResponseComponentBuilder.createSAMLResponse(
+                "http://cxf.apache.org/saml", "http://cxf.apache.org/issuer", status
+            );
+        
+        // Create an AuthenticationAssertion
+        SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
+        callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
+        callbackHandler.setIssuer("http://cxf.apache.org/issuer");
+        callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
+        
+        SAMLCallback samlCallback = new SAMLCallback();
+        SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
+        SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
+        
+        Crypto issuerCrypto = new Merlin();
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        ClassLoader loader = Loader.getClassLoader(SAMLResponseValidatorTest.class);
+        InputStream input = Merlin.loadInputStream(loader, "alice.jks");
+        keyStore.load(input, "password".toCharArray());
+        ((Merlin)issuerCrypto).setKeyStore(keyStore);
+        
+        response.getAssertions().add(assertion.getSaml2());
+        signResponse(response, "alice", "password", issuerCrypto, false);
+        
+        Element policyElement = OpenSAMLUtil.toDom(response, doc);
+        doc.appendChild(policyElement);
+        assertNotNull(policyElement);
+        
+        Response marshalledResponse = (Response)OpenSAMLUtil.fromDom(policyElement);
+        
+        // Validate the Response
+        SAMLProtocolResponseValidator validator = new SAMLProtocolResponseValidator();
+        validator.setKeyInfoMustBeAvailable(false);
+        try {
+            validator.validateSamlResponse(marshalledResponse, null, new KeystorePasswordCallback());
+            fail("Expected failure on no Signature Crypto");
+        } catch (WSSecurityException ex) {
+            // expected
+        }
+        
+        // Validate the Response
+        validator.validateSamlResponse(
+            marshalledResponse, issuerCrypto, new KeystorePasswordCallback()
+        );
+    }
 
     
     /**
@@ -267,7 +325,8 @@ public class SAMLResponseValidatorTest e
         Response response,
         String issuerKeyName,
         String issuerKeyPassword,
-        Crypto issuerCrypto
+        Crypto issuerCrypto,
+        boolean useKeyInfo
     ) throws Exception {
         //
         // Create the signature
@@ -302,15 +361,17 @@ public class SAMLResponseValidatorTest e
 
         signature.setSigningCredential(signingCredential);
 
-        X509KeyInfoGeneratorFactory kiFactory = new X509KeyInfoGeneratorFactory();
-        kiFactory.setEmitEntityCertificate(true);
-        
-        try {
-            KeyInfo keyInfo = kiFactory.newInstance().generate(signingCredential);
-            signature.setKeyInfo(keyInfo);
-        } catch (org.opensaml.xml.security.SecurityException ex) {
-            throw new Exception(
-                    "Error generating KeyInfo from signing credential", ex);
+        if (useKeyInfo) {
+            X509KeyInfoGeneratorFactory kiFactory = new X509KeyInfoGeneratorFactory();
+            kiFactory.setEmitEntityCertificate(true);
+            
+            try {
+                KeyInfo keyInfo = kiFactory.newInstance().generate(signingCredential);
+                signature.setKeyInfo(keyInfo);
+            } catch (org.opensaml.xml.security.SecurityException ex) {
+                throw new Exception(
+                        "Error generating KeyInfo from signing credential", ex);
+            }
         }
 
         // add the signature to the assertion

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java Mon Dec 23 17:30:03 2013
@@ -26,6 +26,7 @@ import java.security.PublicKey;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.List;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.ws.rs.NotAuthorizedException;
@@ -47,6 +48,8 @@ import org.apache.cxf.security.SecurityC
 import org.apache.cxf.security.transport.TLSSessionInfo;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
 import org.apache.wss4j.common.saml.SAMLKeyInfo;
 import org.apache.wss4j.common.saml.SAMLUtil;
@@ -74,6 +77,7 @@ public abstract class AbstractSamlInHand
     }
     
     private Validator samlValidator = new SamlAssertionValidator();
+    private boolean keyInfoMustBeAvailable = true;
     private SecurityContextProvider scProvider = new SecurityContextProviderImpl(); 
     
     public void setValidator(Validator validator) {
@@ -135,13 +139,18 @@ public abstract class AbstractSamlInHand
                     message.getContextualProperty(WSHandlerConstants.ENABLE_REVOCATION)));
                 Signature sig = assertion.getSignature();
                 WSDocInfo docInfo = new WSDocInfo(sig.getDOM().getOwnerDocument());
-                KeyInfo keyInfo = sig.getKeyInfo();
                 
-                SAMLKeyInfo samlKeyInfo = 
-                    SAMLUtil.getCredentialFromKeyInfo(
+                SAMLKeyInfo samlKeyInfo = null;
+                
+                KeyInfo keyInfo = sig.getKeyInfo();
+                if (keyInfo != null) {
+                    samlKeyInfo = SAMLUtil.getCredentialFromKeyInfo(
                         keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(data, docInfo), 
                         data.getSigVerCrypto()
                     );
+                } else if (!keyInfoMustBeAvailable) {
+                    samlKeyInfo = createKeyInfoFromDefaultAlias(data.getSigVerCrypto());
+                }
                 
                 assertion.verifySignature(samlKeyInfo);
                 assertion.parseHOKSubject(
@@ -166,6 +175,19 @@ public abstract class AbstractSamlInHand
         }
     }
     
+    protected SAMLKeyInfo createKeyInfoFromDefaultAlias(Crypto sigCrypto) throws WSSecurityException {
+        try {
+            X509Certificate[] certs = SecurityUtils.getCertificates(sigCrypto, 
+                                                                    sigCrypto.getDefaultX509Identifier());
+            SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(new X509Certificate[]{certs[0]});
+            samlKeyInfo.setPublicKey(certs[0].getPublicKey());
+            return samlKeyInfo;
+        } catch (Exception ex) {
+            LOG.log(Level.FINE, "Error in loading the certificates: " + ex.getMessage(), ex);
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex);
+        }
+    }
+    
     protected void checkSubjectConfirmationData(Message message, SamlAssertionWrapper assertion) {
         Certificate[] tlsCerts = getTLSCertificates(message);
         if (!checkHolderOfKey(message, assertion, tlsCerts)) {
@@ -331,4 +353,8 @@ public abstract class AbstractSamlInHand
         return confirmMethod != null && confirmMethod.startsWith("urn:oasis:names:tc:SAML:") 
                 && confirmMethod.endsWith(":cm:bearer");
     }
+
+    public void setKeyInfoMustBeAvailable(boolean keyInfoMustBeAvailable) {
+        this.keyInfoMustBeAvailable = keyInfoMustBeAvailable;
+    }
 }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/AbstractXmlSigInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/AbstractXmlSigInHandler.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/AbstractXmlSigInHandler.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/AbstractXmlSigInHandler.java Mon Dec 23 17:30:03 2013
@@ -34,6 +34,7 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.rs.security.common.CryptoLoader;
 import org.apache.cxf.rs.security.common.SecurityUtils;
 import org.apache.cxf.rs.security.common.TrustValidator;
+import org.apache.cxf.security.SecurityContext;
 import org.apache.cxf.staxutils.W3CDOMStreamReader;
 import org.apache.cxf.ws.security.SecurityConstants;
 import org.apache.wss4j.common.crypto.Crypto;
@@ -51,6 +52,7 @@ public class AbstractXmlSigInHandler ext
     
     private boolean removeSignature = true;
     private boolean persistSignature = true;
+    private boolean keyInfoMustBeAvailable = true;
     private SignatureProperties sigProps;
     
     public void setRemoveSignature(boolean remove) {
@@ -114,22 +116,32 @@ public class AbstractXmlSigInHandler ext
                 signedElement.setIdAttributeNS(null, "ID", true);
             }
             
+            X509Certificate cert = null;
+            PublicKey publicKey = null;
+            
+            
             // See also WSS4J SAMLUtil.getCredentialFromKeyInfo 
             KeyInfo keyInfo = signature.getKeyInfo();
             
-            X509Certificate cert = keyInfo.getX509Certificate();
-            if (cert != null) {
+            if (keyInfo != null) {
+                cert = keyInfo.getX509Certificate();
+                if (cert != null) {
+                    valid = signature.checkSignatureValue(cert);
+                } else {
+                    publicKey = keyInfo.getPublicKey();
+                    if (publicKey != null) {
+                        valid = signature.checkSignatureValue(publicKey);
+                    }
+                } 
+            } else if (!keyInfoMustBeAvailable) {
+                String user = getUserName(crypto, message);
+                cert = SecurityUtils.getCertificates(crypto, user)[0];
+                publicKey = cert.getPublicKey();
                 valid = signature.checkSignatureValue(cert);
-            } else {
-                PublicKey pk = keyInfo.getPublicKey();
-                if (pk != null) {
-                    valid = signature.checkSignatureValue(pk);
-                }
             }
             
             // validate trust 
-            new TrustValidator().validateTrust(crypto, cert, keyInfo.getPublicKey());
-            
+            new TrustValidator().validateTrust(crypto, cert, publicKey);
             if (valid && persistSignature) {
                 message.setContent(XMLSignature.class, signature);
                 message.setContent(Element.class, signedElement);
@@ -158,6 +170,16 @@ public class AbstractXmlSigInHandler ext
         
     }
     
+    protected String getUserName(Crypto crypto, Message message) {
+        SecurityContext sc = message.get(SecurityContext.class);
+        if (sc != null && sc.getUserPrincipal() != null) {
+            return sc.getUserPrincipal().getName();
+        } else {
+            return SecurityUtils.getUserName(crypto, null);
+        }
+        
+    }
+    
     private Element getActualBody(Element envelopingSigElement) {
         Element objectNode = getNode(envelopingSigElement, Constants.SignatureSpecNS, "Object", 0);
         if (objectNode == null) {
@@ -341,4 +363,8 @@ public class AbstractXmlSigInHandler ext
     public void setSignatureProperties(SignatureProperties properties) {
         this.sigProps = properties;
     }
+    
+    public void setKeyInfoMustBeAvailable(boolean use) {
+        this.keyInfoMustBeAvailable = use;
+    }
 }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/xml/XmlSigOutInterceptor.java Mon Dec 23 17:30:03 2013
@@ -65,7 +65,7 @@ public class XmlSigOutInterceptor extend
     
     private QName envelopeQName = DEFAULT_ENV_QNAME;
     private String sigStyle = ENVELOPED_SIG;
-    
+    private boolean keyInfoMustBeAvailable = true;    
     private SignatureProperties sigProps = new SignatureProperties();
     
     public XmlSigOutInterceptor() {
@@ -82,6 +82,10 @@ public class XmlSigOutInterceptor extend
         sigStyle = style;    
     }
     
+    public void setKeyInfoMustBeAvailable(boolean use) {
+        this.keyInfoMustBeAvailable = use;
+    }
+    
     public void setSignatureAlgorithm(String algo) {
         sigProps.setSignatureAlgo(algo);
     }
@@ -148,9 +152,10 @@ public class XmlSigOutInterceptor extend
             sig = prepareEnvelopedSignature(doc, id, referenceId, sigAlgo, digestAlgo);
         }
         
-        
-        sig.addKeyInfo(issuerCerts[0]);
-        sig.addKeyInfo(issuerCerts[0].getPublicKey());
+        if (this.keyInfoMustBeAvailable) {
+            sig.addKeyInfo(issuerCerts[0]);
+            sig.addKeyInfo(issuerCerts[0].getPublicKey());
+        }
         sig.sign(privateKey);
         return sig.getElement().getOwnerDocument();
     }

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/JAXRSXmlSecTest.java Mon Dec 23 17:30:03 2013
@@ -116,22 +116,31 @@ public class JAXRSXmlSecTest extends Abs
     @Test
     public void testPostBookWithEnvelopedSig() throws Exception {
         String address = "https://localhost:" + PORT + "/xmlsig/bookstore/books";
-        doTestSignature(address, false, false);
+        doTestSignature(address, false, false, true);
+    }
+    
+    @Test
+    public void testPostBookWithEnvelopedSigNoKeyInfo() throws Exception {
+        String address = "https://localhost:" + PORT + "/xmlsignokeyinfo/bookstore/books";
+        doTestSignature(address, false, false, false);
     }
     
     @Test
     public void testPostBookWithEnvelopingSig() throws Exception {
         String address = "https://localhost:" + PORT + "/xmlsig/bookstore/books";
-        doTestSignature(address, true, false);
+        doTestSignature(address, true, false, true);
     }
     
     @Test
     public void testPostBookWithEnvelopingSigFromResponse() throws Exception {
         String address = "https://localhost:" + PORT + "/xmlsig/bookstore/books";
-        doTestSignature(address, true, true);
+        doTestSignature(address, true, true, true);
     }
     
-    private void doTestSignature(String address, boolean enveloping, boolean fromResponse) {
+    private void doTestSignature(String address, 
+                                 boolean enveloping, 
+                                 boolean fromResponse,
+                                 boolean useKeyInfo) {
         JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
         bean.setAddress(address);
         
@@ -147,14 +156,18 @@ public class JAXRSXmlSecTest extends Abs
         properties.put("ws-security.signature.properties", 
                        "org/apache/cxf/systest/jaxrs/security/alice.properties");
         bean.setProperties(properties);
-        XmlSigOutInterceptor sigInterceptor = new XmlSigOutInterceptor();
+        XmlSigOutInterceptor sigOutInterceptor = new XmlSigOutInterceptor();
         if (enveloping) {
-            sigInterceptor.setStyle(XmlSigOutInterceptor.ENVELOPING_SIG);
+            sigOutInterceptor.setStyle(XmlSigOutInterceptor.ENVELOPING_SIG);
         }
-        bean.getOutInterceptors().add(sigInterceptor);
-        bean.getInInterceptors().add(new XmlSigInInterceptor());
+        sigOutInterceptor.setKeyInfoMustBeAvailable(useKeyInfo);
+        bean.getOutInterceptors().add(sigOutInterceptor);
+        XmlSigInInterceptor sigInInterceptor = new XmlSigInInterceptor();
+        sigInInterceptor.setKeyInfoMustBeAvailable(useKeyInfo);
+        bean.getInInterceptors().add(sigInInterceptor);
         
         WebClient wc = bean.createWebClient();
+        WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000L);
         try {
             Book book;
             if (!fromResponse) {

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/server.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/server.xml?rev=1553156&r1=1553155&r2=1553156&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/server.xml (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/server.xml Mon Dec 23 17:30:03 2013
@@ -60,10 +60,16 @@ under the License.
     <bean id="xmlSigInHandlerWithProps" class="org.apache.cxf.rs.security.xml.XmlSigInHandler">
         <property name="signatureProperties" ref="sigProps"/>
     </bean>
+    <bean id="xmlSigInHandlerNoKeyInfo" class="org.apache.cxf.rs.security.xml.XmlSigInHandler">
+        <property name="keyInfoMustBeAvailable" value="false"/>
+    </bean>
     <bean id="xmlSigOutHandler" class="org.apache.cxf.rs.security.xml.XmlSigOutInterceptor"/>
     <bean id="xmlSigOutHandlerWithProps" class="org.apache.cxf.rs.security.xml.XmlSigOutInterceptor">
         <property name="signatureProperties" ref="sigProps"/>
     </bean>
+    <bean id="xmlSigOutHandlerNoKeyInfo" class="org.apache.cxf.rs.security.xml.XmlSigOutInterceptor">
+        <property name="keyInfoMustBeAvailable" value="false"/>
+    </bean>
     <bean id="xmlEncInHandler" class="org.apache.cxf.rs.security.xml.XmlEncInHandler"/>
     <bean id="xmlEncInHandlerWithProps" class="org.apache.cxf.rs.security.xml.XmlEncInHandler">
         <property name="encryptionProperties" ref="encProps"/>
@@ -89,6 +95,23 @@ under the License.
             <entry key="ws-security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.properties"/>
         </jaxrs:properties>
     </jaxrs:server>
+    
+    <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-xmlsec}/xmlsignokeyinfo">
+        <jaxrs:serviceBeans>
+            <ref bean="serviceBean"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:providers>
+            <ref bean="xmlSigInHandlerNoKeyInfo"/>
+        </jaxrs:providers>
+        <jaxrs:outInterceptors>
+            <ref bean="xmlSigOutHandlerNoKeyInfo"/>
+        </jaxrs:outInterceptors>
+        <jaxrs:properties>
+            <entry key="ws-security.callback-handler" value="org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback"/>
+            <entry key="ws-security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.properties"/>
+        </jaxrs:properties>
+    </jaxrs:server>
+    
     <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-xmlsec}/xmlenc">
         <jaxrs:serviceBeans>
             <ref bean="serviceBean"/>