You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ws.apache.org by co...@apache.org on 2010/11/10 17:35:52 UTC

svn commit: r1033575 - in /webservices/wss4j/trunk: keys/ src/org/apache/ws/security/action/ src/org/apache/ws/security/handler/ src/org/apache/ws/security/processor/ test/ test/wssec/

Author: coheigea
Date: Wed Nov 10 16:35:51 2010
New Revision: 1033575

URL: http://svn.apache.org/viewvc?rev=1033575&view=rev
Log:
[WSS-40] - Committed a fix for trunk.

Added:
    webservices/wss4j/trunk/keys/client_keystore.jks   (with props)
    webservices/wss4j/trunk/keys/server_keystore.jks   (with props)
    webservices/wss4j/trunk/test/wss40_client.properties
    webservices/wss4j/trunk/test/wss40_server.properties
Modified:
    webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java
    webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java
    webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
    webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
    webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java

Added: webservices/wss4j/trunk/keys/client_keystore.jks
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/keys/client_keystore.jks?rev=1033575&view=auto
==============================================================================
Binary file - no diff available.

Propchange: webservices/wss4j/trunk/keys/client_keystore.jks
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: webservices/wss4j/trunk/keys/server_keystore.jks
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/keys/server_keystore.jks?rev=1033575&view=auto
==============================================================================
Binary file - no diff available.

Propchange: webservices/wss4j/trunk/keys/server_keystore.jks
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java Wed Nov 10 16:35:51 2010
@@ -51,6 +51,7 @@ public class SignatureAction implements 
         }
 
         wsSign.setUserInfo(reqData.getSignatureUser(), pwcb.getPassword());
+        wsSign.setUseSingleCertificate(reqData.isUseSingleCert());
         if (reqData.getSignatureParts().size() > 0) {
             wsSign.setParts(reqData.getSignatureParts());
         }

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java Wed Nov 10 16:35:51 2010
@@ -66,6 +66,7 @@ public class RequestData {
     private boolean useDerivedKey = true;
     private int derivedKeyIterations = UsernameToken.DEFAULT_ITERATION;
     private boolean useDerivedKeyForMAC = true;
+    private boolean useSingleCert = true;
 
     public void clear() {
         soapConstants = null;
@@ -84,6 +85,7 @@ public class RequestData {
         useDerivedKey = true;
         derivedKeyIterations = UsernameToken.DEFAULT_ITERATION;
         useDerivedKeyForMAC = true;
+        useSingleCert = true;
     }
 
     public Object getMsgContext() {
@@ -353,4 +355,22 @@ public class RequestData {
         return useDerivedKeyForMAC;
     }
     
+    /**
+     * Whether to use a single certificate or a whole certificate chain when
+     * constructing a BinarySecurityToken used for direct reference in Signature.
+     * @param useSingleCert true if only to use a single certificate
+     */
+    public void setUseSingleCert(boolean useSingleCert) {
+        this.useSingleCert = useSingleCert;
+    }
+    
+    /**
+     * Whether to use a single certificate or a whole certificate chain when
+     * constructing a BinarySecurityToken used for direct reference in Signature.
+     * @return whether to use a single certificate
+     */
+    public boolean isUseSingleCert() {
+        return useSingleCert;
+    }
+    
 }

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java Wed Nov 10 16:35:51 2010
@@ -597,6 +597,9 @@ public abstract class WSHandler {
             int iSecretKeyLength = Integer.parseInt(secretKeyLength);
             reqData.setSecretKeyLength(iSecretKeyLength);
         }
+        
+        boolean useSingleCert = decodeUseSingleCertificate(reqData);
+        reqData.setUseSingleCert(useSingleCert);
     }
 
     protected void decodeEncryptionParameter(RequestData reqData) 
@@ -826,6 +829,26 @@ public abstract class WSHandler {
             "WSHandler: illegal timestampStrict parameter"
         );
     }
+    
+    protected boolean decodeUseSingleCertificate(RequestData reqData) 
+        throws WSSecurityException {
+        String useSingleCert = 
+            getString(WSHandlerConstants.USE_SINGLE_CERTIFICATE, reqData.getMsgContext());
+    
+        if (useSingleCert == null) {
+            return true;
+        }
+        if ("0".equals(useSingleCert) || "false".equals(useSingleCert)) {
+            return false;
+        } 
+        if ("1".equals(useSingleCert) || "true".equals(useSingleCert)) {
+            return true;
+        }
+    
+        throw new WSSecurityException(
+            "WSHandler: illegal useSingleCert parameter"
+        );
+    }
 
     /**
      * Get a password to construct a UsernameToken or sign a message.

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java Wed Nov 10 16:35:51 2010
@@ -596,6 +596,13 @@ public class WSHandlerConstants {
     public static final String SIGNATURE_PARTS = "signatureParts";
     
     /**
+     * This parameter sets whether to use a single certificate or a whole certificate
+     * chain when constructing a BinarySecurityToken used for direct reference in
+     * signature. The default is true, meaning that only a single certificate is used.
+     */
+    public static final String USE_SINGLE_CERTIFICATE = "useSingleCertificate";
+    
+    /**
      * This parameter sets the length of the secret (derived) key to use for the
      * WSE UT_SIGN functionality.
      * 

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java Wed Nov 10 16:35:51 2010
@@ -194,6 +194,7 @@ public class SignatureProcessor implemen
         PublicKey publicKey = null;
         Principal principal = null;
         KeyValue keyValue = null;
+        boolean validateCertificateChain = false;
         
         Element keyInfoElement = 
             WSSecurityUtil.getDirectChildElement(
@@ -256,7 +257,9 @@ public class SignatureProcessor implemen
                         QName el = new QName(token.getNamespaceURI(), token.getLocalName());
                         if (el.equals(WSSecurityEngine.BINARY_TOKEN)) {
                             certs = getCertificatesTokenReference(token, crypto);
-                            principal = validateCertificates(certs, crypto);
+                            if (certs != null && certs.length > 1) {
+                                validateCertificateChain = true;
+                            }
                         } else if (el.equals(WSSecurityEngine.SAML_TOKEN)) {
                             if (crypto == null) {
                                 throw new WSSecurityException(
@@ -265,7 +268,6 @@ public class SignatureProcessor implemen
                             }
                             SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(token, crypto, cb);
                             certs = samlKi.getCerts();
-                            validateCertificates(certs, crypto);
                             secretKey = samlKi.getSecret();
                             principal = createPrincipalFromSAMLKeyInfo(samlKi);
                         } else if (el.equals(WSSecurityEngine.ENCRYPTED_KEY)){
@@ -295,7 +297,9 @@ public class SignatureProcessor implemen
                         principal = ut.createPrincipal();
                     } else if (processor instanceof BinarySecurityTokenProcessor) {
                         certs = ((BinarySecurityTokenProcessor)processor).getCertificates();
-                        principal = validateCertificates(certs, crypto);
+                        if (certs != null && certs.length > 1) {
+                            validateCertificateChain = true;
+                        }
                     } else if (processor instanceof EncryptedKeyProcessor) {
                         EncryptedKeyProcessor encryptedKeyProcessor = 
                             (EncryptedKeyProcessor)processor;
@@ -327,14 +331,12 @@ public class SignatureProcessor implemen
                         SAMLKeyInfo samlKi = 
                             SAMLUtil.getSAMLKeyInfo(samlp.getSamlTokenElement(), crypto, cb);
                         certs = samlKi.getCerts();
-                        validateCertificates(certs, crypto);
                         secretKey = samlKi.getSecret();
                         publicKey = samlKi.getPublicKey();
                         principal = createPrincipalFromSAMLKeyInfo(samlKi);
                     }
                 } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
                     certs = secRef.getX509IssuerSerial(crypto);
-                    principal = validateCertificates(certs, crypto);
                 } else if (secRef.containsKeyIdentifier()) {
                     if (secRef.getKeyIdentifierValueType().equals(SecurityTokenReference.ENC_KEY_SHA1_URI)) {
                         String id = secRef.getKeyIdentifierValue();
@@ -351,13 +353,11 @@ public class SignatureProcessor implemen
                         }
                         SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(token, crypto, cb);
                         certs = samlKi.getCerts();
-                        validateCertificates(certs, crypto);
                         secretKey = samlKi.getSecret();
                         publicKey = samlKi.getPublicKey();
                         principal = createPrincipalFromSAMLKeyInfo(samlKi);
                     } else {
                         certs = secRef.getKeyIdentifier(crypto);
-                        principal = validateCertificates(certs, crypto);
                     }
                 } else {
                     throw new WSSecurityException(
@@ -379,6 +379,25 @@ public class SignatureProcessor implemen
             && publicKey == null) {
             throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
         }
+        
+        //
+        // Validate certificates and verify trust
+        //
+        validateCertificates(certs);
+        if (certs != null) {
+            if (principal == null) {
+                principal = certs[0].getSubjectX500Principal();
+            }
+            boolean trust = false;
+            if (!validateCertificateChain || certs.length == 1) {
+                trust = verifyTrust(certs[0], crypto);
+            } else if (validateCertificateChain && certs.length > 1) {
+                trust = verifyTrust(certs, crypto);
+            }
+            if (!trust) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+            }
+        }
 
         //
         // Perform the signature verification and build up a List of elements that the
@@ -442,15 +461,12 @@ public class SignatureProcessor implemen
     
     
     /**
-     * Validate an array of certificates by checking the validity of each cert, and verifying trust
+     * Validate an array of certificates by checking the validity of each cert
      * @param certsToValidate The array of certificates to validate
-     * @param crypto The crypto object representing the keystore
-     * @return A principal representing the first element in the array (if it exists)
      * @throws WSSecurityException
      */
-    public static Principal validateCertificates(
-        X509Certificate[] certsToValidate,
-        Crypto crypto
+    public static void validateCertificates(
+        X509Certificate[] certsToValidate
     ) throws WSSecurityException {
         if (certsToValidate != null && certsToValidate.length > 0) {
             try {
@@ -466,12 +482,7 @@ public class SignatureProcessor implemen
                     WSSecurityException.FAILED_CHECK, "invalidCert", null, e
                 );
             }
-            if (!verifyTrust(certsToValidate[0], crypto)) {
-                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
-            }
-            return certsToValidate[0].getSubjectX500Principal();
         }
-        return null;
     }
     
     
@@ -570,7 +581,7 @@ public class SignatureProcessor implemen
                 x509certs[j + 1] = certs[j];
             }
 
-            ///
+            //
             // Use the validation method from the crypto to check whether the subjects' 
             // certificate was really signed by the issuer stated in the certificate
             //
@@ -594,6 +605,43 @@ public class SignatureProcessor implemen
         return false;
     }
     
+
+    /**
+     * Evaluate whether the given certificate chain should be trusted.
+     * 
+     * @param certificates the certificate chain that should be validated against the keystore
+     * @return true if the certificate chain is trusted, false if not
+     * @throws WSSecurityException
+     */
+    public static boolean verifyTrust(X509Certificate[] certificates, Crypto crypto) 
+        throws WSSecurityException {
+        String subjectString = certificates[0].getSubjectX500Principal().getName();
+        //
+        // Use the validation method from the crypto to check whether the subjects' 
+        // certificate was really signed by the issuer stated in the certificate
+        //
+        if (certificates != null && certificates.length > 1
+            && crypto.validateCertPath(certificates)) {
+            if (log.isDebugEnabled()) {
+                log.debug(
+                    "Certificate path has been verified for certificate with subject " 
+                    + subjectString
+                );
+            }
+            return true;
+        }
+        
+        if (log.isDebugEnabled()) {
+            log.debug(
+                "Certificate path could not be verified for certificate with subject " 
+                + subjectString
+            );
+        }
+            
+        return false;
+    }
+    
+    
     
     /**
      * Get the default principal from the KeyStore

Added: webservices/wss4j/trunk/test/wss40_client.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wss40_client.properties?rev=1033575&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wss40_client.properties (added)
+++ webservices/wss4j/trunk/test/wss40_client.properties Wed Nov 10 16:35:51 2010
@@ -0,0 +1,5 @@
+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=Client_CertChain
+org.apache.ws.security.crypto.merlin.keystore.file=keys/client_keystore.jks

Added: webservices/wss4j/trunk/test/wss40_server.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wss40_server.properties?rev=1033575&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wss40_server.properties (added)
+++ webservices/wss4j/trunk/test/wss40_server.properties Wed Nov 10 16:35:51 2010
@@ -0,0 +1,5 @@
+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=CA_Cert
+org.apache.ws.security.crypto.merlin.keystore.file=keys/server_keystore.jks

Modified: webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java (original)
+++ webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java Wed Nov 10 16:35:51 2010
@@ -25,12 +25,15 @@ import junit.framework.TestSuite;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
 import org.apache.ws.security.WSSecurityEngine;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSSecurityEngineResult;
 import org.apache.ws.security.WSSecurityException;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
 import org.apache.ws.security.message.WSSecSignature;
 import org.apache.ws.security.message.WSSecHeader;
 import org.apache.ws.security.util.WSSecurityUtil;
@@ -108,7 +111,6 @@ public class TestWSSecurityWSS40 extends
         return new TestSuite(TestWSSecurityWSS40.class);
     }
 
-    
     /**
      * Test signing a SOAP message using a BST.
      */
@@ -139,6 +141,40 @@ public class TestWSSecurityWSS40 extends
         assertTrue (cert != null);
     }
     
+    public void testBSTCertChain() throws Exception {
+        Crypto clientCrypto = CryptoFactory.getInstance("wss40_client.properties");
+        WSSecSignature sign = new WSSecSignature();
+        sign.setUserInfo("Client_CertChain", "password");
+        sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        sign.setUseSingleCertificate(false);
+       
+        Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = sign.build(doc, clientCrypto, secHeader);
+                
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+            LOG.debug("BST CA Cert");
+            LOG.debug(outputString);
+        }
+        //
+        // Verify the signature
+        //
+        Crypto serverCrypto = CryptoFactory.getInstance("wss40_server.properties");
+        List results = verify(signedDoc, serverCrypto);
+        WSSecurityEngineResult result = 
+            WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
+        X509Certificate cert = 
+            (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+        assertTrue (cert != null);
+        X509Certificate[] certs = 
+            (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+        assertTrue (certs != null && certs.length == 2);
+    }
+    
     /**
      * Test signing a SOAP message using a BST, sending the CA cert as well in the
      * message.
@@ -170,6 +206,9 @@ public class TestWSSecurityWSS40 extends
         X509Certificate cert = 
             (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
         assertTrue (cert != null);
+        X509Certificate[] certs = 
+            (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+        assertTrue (certs != null && certs.length == 2);
     }
     
     
@@ -237,6 +276,48 @@ public class TestWSSecurityWSS40 extends
         }
     }
     
+    /**
+     * A test for "SignatureAction does not set DigestAlgorithm on WSSecSignature instance"
+     */
+    public void testMultipleCertsWSHandler() throws Exception {
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final int action = WSConstants.SIGN;
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setUsername("wss40");
+        java.util.Map config = new java.util.TreeMap();
+        config.put(WSHandlerConstants.SIG_PROP_FILE, "wss40.properties");
+        config.put("password", "security");
+        config.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+        config.put(WSHandlerConstants.USE_SINGLE_CERTIFICATE, "false");
+        reqData.setMsgContext(config);
+        
+        final java.util.Vector actions = new java.util.Vector();
+        actions.add(new Integer(action));
+        final Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+        MyHandler handler = new MyHandler();
+        handler.send(
+            action, 
+            doc, 
+            reqData, 
+            actions,
+            true
+        );
+        
+        //
+        // Verify the signature
+        //
+        List results = verify(doc, cryptoCA);
+        WSSecurityEngineResult result = 
+            WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
+        X509Certificate cert = 
+            (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+        assertTrue (cert != null);
+        X509Certificate[] certs = 
+            (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+        assertTrue (certs != null && certs.length == 2);
+    }
+    
     
     /**
      * Verifies the soap envelope



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ws.apache.org
For additional commands, e-mail: dev-help@ws.apache.org