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 2011/08/08 16:44:01 UTC

svn commit: r1154974 - in /cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security: common/SecurityUtils.java xml/JAXRSXmlSecTest.java xml/XmlEncInHandler.java xml/XmlEncOutInterceptor.java xml/XmlSigOutInterceptor.java

Author: sergeyb
Date: Mon Aug  8 14:44:01 2011
New Revision: 1154974

URL: http://svn.apache.org/viewvc?rev=1154974&view=rev
Log:
[CXF-3677] Fixing the position of EncryptedKey, some flexibility in the way X509 key identifiers are handled

Modified:
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/common/SecurityUtils.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/XmlEncInHandler.java
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncOutInterceptor.java
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlSigOutInterceptor.java

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/common/SecurityUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/common/SecurityUtils.java?rev=1154974&r1=1154973&r2=1154974&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/common/SecurityUtils.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/common/SecurityUtils.java Mon Aug  8 14:44:01 2011
@@ -19,12 +19,18 @@
 
 package org.apache.cxf.systest.jaxrs.security.common;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.math.BigInteger;
 import java.security.cert.X509Certificate;
 
 import javax.security.auth.callback.CallbackHandler;
 
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
 import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Message;
@@ -33,13 +39,36 @@ import org.apache.ws.security.WSPassword
 import org.apache.ws.security.WSSecurityException;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoType;
+import org.apache.xml.security.utils.Constants;
 
 public final class SecurityUtils {
     
+    public static final String X509_KEY = "X509_KEY";
+    public static final String X509_ISSUER_SERIAL = "X509_ISSUER_SERIAL";
+    
     private SecurityUtils() {
         
     }
     
+    public static X509Certificate loadX509Certificate(Crypto crypto, Element certNode) 
+        throws Exception {
+        String base64Value = certNode.getTextContent().trim();
+        byte[] certBytes = Base64Utility.decode(base64Value);
+        return crypto.loadCertificate(new ByteArrayInputStream(certBytes));
+    }
+    
+    public static X509Certificate loadX509IssuerSerial(Crypto crypto, Element certNode) 
+        throws Exception {
+        Node issuerNameNode = 
+            certNode.getElementsByTagNameNS(Constants.SignatureSpecNS, "X509IssuerName").item(0);
+        Node serialNumberNode = 
+            certNode.getElementsByTagNameNS(Constants.SignatureSpecNS, "X509SerialNumber").item(0);
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ISSUER_SERIAL);
+        cryptoType.setIssuerSerial(issuerNameNode.getTextContent(), 
+                                   new BigInteger(serialNumberNode.getTextContent()));
+        return crypto.getX509Certificates(cryptoType)[0];
+    }
+    
     public static X509Certificate[] getCertificates(Crypto crypto, String user)
         throws WSSecurityException {
         CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);

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=1154974&r1=1154973&r2=1154974&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 Aug  8 14:44:01 2011
@@ -30,6 +30,7 @@ import org.apache.cxf.jaxrs.client.JAXRS
 import org.apache.cxf.jaxrs.client.ServerWebApplicationException;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.systest.jaxrs.security.Book;
+import org.apache.cxf.systest.jaxrs.security.common.SecurityUtils;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 import org.apache.xml.security.encryption.XMLCipher;
 import org.junit.BeforeClass;
@@ -84,39 +85,25 @@ public class JAXRSXmlSecTest extends Abs
     @Test
     public void testPostEncryptedBook() throws Exception {
         String address = "https://localhost:" + PORT + "/xmlenc/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<String, Object>();
         properties.put("ws-security.callback-handler", 
                        "org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback");
         properties.put("ws-security.encryption.username", "bob");
         properties.put("ws-security.encryption.properties", 
                        "org/apache/cxf/systest/jaxrs/security/bob.properties");
-        bean.setProperties(properties);
-        XmlEncOutInterceptor encInterceptor = new XmlEncOutInterceptor();
-        encInterceptor.setSymmetricEncAlgorithm(XMLCipher.AES_128);
-        bean.getOutInterceptors().add(encInterceptor);
-                
-        WebClient wc = bean.createWebClient();
-        try {
-            Book book = wc.post(new Book("CXF", 126L), Book.class);
-            assertEquals(126L, book.getId());
-        } catch (ServerWebApplicationException ex) {
-            fail(ex.getMessage());
-        } catch (ClientWebApplicationException ex) {
-            if (ex.getCause() != null && ex.getCause().getMessage() != null) {
-                fail(ex.getCause().getMessage());
-            } else {
-                fail(ex.getMessage());
-            }
-        }
-        
+        doTestPostEncryptedBook(address, properties);
+    }
+    
+    @Test
+    public void testPostEncryptedBookIssuerSerial() throws Exception {
+        String address = "https://localhost:" + PORT + "/xmlenc/bookstore/books";
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("ws-security.callback-handler", 
+                       "org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback");
+        properties.put("ws-security.encryption.username", "bob");
+        properties.put("ws-security.encryption.properties", 
+                       "org/apache/cxf/systest/jaxrs/security/bob.properties");
+        doTestPostEncryptedBook(address, properties, SecurityUtils.X509_ISSUER_SERIAL);
     }
     
     @Test
@@ -131,7 +118,7 @@ public class JAXRSXmlSecTest extends Abs
         properties.put("ws-security.signature.username", "alice");
         properties.put("ws-security.signature.properties", 
                        "org/apache/cxf/systest/jaxrs/security/alice.properties");
-        doTestPostEncryptedSignedBook(address, properties);
+        doTestPostEncryptedBook(address, properties);
         
     }
     
@@ -145,11 +132,17 @@ public class JAXRSXmlSecTest extends Abs
         properties.put("ws-security.encryption.username", "bob");
         properties.put("ws-security.encryption.properties", 
                        "org/apache/cxf/systest/jaxrs/security/bob.properties");
-        doTestPostEncryptedSignedBook(address, properties);
+        doTestPostEncryptedBook(address, properties);
         
     }
     
-    public void doTestPostEncryptedSignedBook(String address, Map<String, Object> properties) 
+    public void doTestPostEncryptedBook(String address, Map<String, Object> properties) 
+        throws Exception {
+        doTestPostEncryptedBook(address, properties, SecurityUtils.X509_KEY);
+    }
+    
+    public void doTestPostEncryptedBook(String address, Map<String, Object> properties,
+                                        String keyIdentifierType) 
         throws Exception {
         JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
         bean.setAddress(address);
@@ -162,6 +155,7 @@ public class JAXRSXmlSecTest extends Abs
         bean.setProperties(properties);
         bean.getOutInterceptors().add(new XmlSigOutInterceptor());
         XmlEncOutInterceptor encInterceptor = new XmlEncOutInterceptor();
+        encInterceptor.setKeyIdentifierType(keyIdentifierType);
         encInterceptor.setSymmetricEncAlgorithm(XMLCipher.AES_128);
         bean.getOutInterceptors().add(encInterceptor);
         

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncInHandler.java?rev=1154974&r1=1154973&r2=1154974&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncInHandler.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncInHandler.java Mon Aug  8 14:44:01 2011
@@ -109,26 +109,8 @@ public class XmlEncInHandler implements 
         return null;
     }
     
+    // Subclasses can overwrite it and return the bytes, assuming they know the actual key
     protected byte[] getSymmetricKeyBytes(Message message, Element encDataElement) {
-        // Subclasses can overwrite it and return the bytes, assuming they know the actual key
-        Element encKeyElement = getNode(encDataElement, WSConstants.ENC_NS, "EncryptedKey", 0);
-        if (encKeyElement == null) {
-            //TODO: support EncryptedData/ds:KeyInfo - the encrypted key is passed out of band
-            throwFault("EncryptedKey element is not available", null);
-        }
-        
-        Element certNode = getNode(encKeyElement, 
-                                      Constants.SignatureSpecNS, "X509Certificate", 0);
-        if (certNode == null) {
-            throwFault("Certificate is missing", null);
-        }
-        byte[] certBytes = null;
-        try {
-            certBytes = Base64Utility.decode(certNode.getTextContent().trim());
-        } catch (Base64Exception ex) {
-            throwFault("Base64 decoding has failed", ex);
-        }
-        
         Crypto crypto = null;
         try {
             crypto = new CryptoLoader().getCrypto(message,
@@ -138,13 +120,14 @@ public class XmlEncInHandler implements 
             throwFault("Crypto can not be loaded", ex);
         }
         
-        X509Certificate cert = null;
-        try {
-            cert = crypto.loadCertificate(new ByteArrayInputStream(certBytes));
-        } catch (Exception ex) {
-            throwFault("X509Certificate can not be created", ex);
+        Element encKeyElement = getNode(encDataElement, WSConstants.ENC_NS, "EncryptedKey", 0);
+        if (encKeyElement == null) {
+            //TODO: support EncryptedData/ds:KeyInfo - the encrypted key is passed out of band
+            throwFault("EncryptedKey element is not available", null);
         }
         
+        X509Certificate cert = loadCertificate(crypto, encKeyElement);
+        
         try {
             new TrustValidator().validateTrust(crypto, cert, null);
         } catch (Exception ex) {
@@ -170,6 +153,36 @@ public class XmlEncInHandler implements 
         return null;
     }
     
+    private X509Certificate loadCertificate(Crypto crypto, Element encKeyElement) {
+        /**
+         * TODO: the following can be easily supported too  
+         <X509SKI>31d97bd7</X509SKI>
+         <X509SubjectName>Subject of Certificate B</X509SubjectName>
+         * 
+         */
+        
+        Element certNode = getNode(encKeyElement, 
+                                   Constants.SignatureSpecNS, "X509Certificate", 0);
+        if (certNode != null) {
+            try {
+                return SecurityUtils.loadX509Certificate(crypto, certNode);
+            } catch (Exception ex) {
+                throwFault("X509Certificate can not be created", ex);
+            }
+        }
+        certNode = getNode(encKeyElement, 
+                Constants.SignatureSpecNS, "X509IssuerSerial", 0);
+        if (certNode != null) {
+            try {
+                return SecurityUtils.loadX509IssuerSerial(crypto, certNode);
+            } catch (Exception ex) {
+                throwFault("X509Certificate can not be created", ex);
+            }
+        }
+        throwFault("Certificate is missing", null);
+        return null;
+    }
+    
     private String getEncodingMethodAlgorithm(Element parent) {
         Element encMethod = getNode(parent, WSConstants.ENC_NS, "EncryptionMethod", 0);
         if (encMethod == null) {

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncOutInterceptor.java?rev=1154974&r1=1154973&r2=1154974&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncOutInterceptor.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlEncOutInterceptor.java Mon Aug  8 14:44:01 2011
@@ -55,18 +55,26 @@ import org.apache.xml.security.algorithm
 import org.apache.xml.security.encryption.XMLCipher;
 
 public class XmlEncOutInterceptor extends AbstractXmlSecOutInterceptor {
+    
     private static final Logger LOG = 
         LogUtils.getL7dLogger(XmlEncOutInterceptor.class);
+    private static final String DEFAULT_RETRIEVAL_METHOD_TYPE =
+        "http://www.w3.org/2001/04/xmlenc#EncryptedKey";
     
     private boolean encryptSymmetricKey = true;
     private SecretKey symmetricKey;
     private String keyEncAlgo = XMLCipher.RSA_OAEP; 
     private String symEncAlgo = XMLCipher.AES_256;
+    private String keyIdentifierType = SecurityUtils.X509_KEY;
     
     public XmlEncOutInterceptor() {
         addAfter(XmlSigOutInterceptor.class.getName());
     } 
 
+    public void setKeyIdentifierType(String type) {
+        keyIdentifierType = type;
+    }
+    
     public void setSymmetricEncAlgorithm(String algo) {
         symEncAlgo = algo;
     }
@@ -208,14 +216,26 @@ public class XmlEncOutInterceptor extend
         String encKeyId = "EK-" + UUIDGenerator.getUUID();
         encryptedKeyElement.setAttributeNS(null, "Id", encKeyId);
                 
-        Element keyInfoElement = createKeyInfoElement(doc, cert, WSConstants.X509_KEY_IDENTIFIER);
+        Element keyInfoElement = createKeyInfoElement(doc, cert);
         encryptedKeyElement.appendChild(keyInfoElement);
         
         Element xencCipherValue = createCipherValue(doc, encryptedKeyElement);
         xencCipherValue.appendChild(doc.createTextNode(encodedKey));
         
+        Element topKeyInfoElement = 
+            doc.createElementNS(
+                WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.KEYINFO_LN
+            );
+        Element retrievalMethodElement = 
+            doc.createElementNS(
+                WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":RetrievalMethod"
+            );
+        retrievalMethodElement.setAttribute("Type", DEFAULT_RETRIEVAL_METHOD_TYPE);
+        topKeyInfoElement.appendChild(retrievalMethodElement);
+        
+        topKeyInfoElement.appendChild(encryptedKeyElement);
         
-        encryptedDataElement.appendChild(encryptedKeyElement);
+        encryptedDataElement.appendChild(topKeyInfoElement);
     }
     
     protected Element createCipherValue(Document doc, Element encryptedKey) {
@@ -229,16 +249,14 @@ public class XmlEncOutInterceptor extend
     }
     
     private Element createKeyInfoElement(Document encryptedDataDoc,
-                                         X509Certificate remoteCert,
-                                         int keyIdentifierType) throws Exception {
+                                         X509Certificate remoteCert) throws Exception {
         Element keyInfoElement = 
             encryptedDataDoc.createElementNS(
                 WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.KEYINFO_LN
             );
         
         Node keyIdentifierNode = null; 
-        switch (keyIdentifierType) {
-        case WSConstants.X509_KEY_IDENTIFIER:
+        if (keyIdentifierType.equals(SecurityUtils.X509_KEY)) {
             byte data[] = null;
             try {
                 data = remoteCert.getEncoded();
@@ -255,10 +273,8 @@ public class XmlEncOutInterceptor extend
                 WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.X509_DATA_LN);
             
             x509Data.appendChild(cert);
-            keyIdentifierNode = x509Data; 
-            break;
-
-        case WSConstants.ISSUER_SERIAL:
+            keyIdentifierNode = x509Data;
+        } else if (keyIdentifierType.equals(SecurityUtils.X509_ISSUER_SERIAL)) {
             String issuer = remoteCert.getIssuerDN().getName();
             java.math.BigInteger serialNumber = remoteCert.getSerialNumber();
             DOMX509IssuerSerial domIssuerSerial = 
@@ -267,8 +283,7 @@ public class XmlEncOutInterceptor extend
                 );
             DOMX509Data domX509Data = new DOMX509Data(encryptedDataDoc, domIssuerSerial);
             keyIdentifierNode = domX509Data.getElement();
-            break;
-        default:
+        } else {
             throw new WSSecurityException("Unsupported key identifier:" + keyIdentifierType);
         }
  

Modified: cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlSigOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlSigOutInterceptor.java?rev=1154974&r1=1154973&r2=1154974&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlSigOutInterceptor.java (original)
+++ cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/xml/XmlSigOutInterceptor.java Mon Aug  8 14:44:01 2011
@@ -46,10 +46,20 @@ public class XmlSigOutInterceptor extend
         LogUtils.getL7dLogger(XmlSigOutInterceptor.class);
     
     private boolean createReferenceId = true;
+    private String defaultSigAlgo = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1;
+    private String digestAlgo = Constants.ALGO_ID_DIGEST_SHA1;
     
     public XmlSigOutInterceptor() {
     } 
 
+    public void setSignatureAlgorithm(String algo) {
+        defaultSigAlgo = algo;
+    }
+    
+    public void setDigestAlgorithm(String algo) {
+        digestAlgo = algo;
+    }
+    
     public void setCreateReferenceId(boolean create) {
         createReferenceId = create;
     }
@@ -87,7 +97,7 @@ public class XmlSigOutInterceptor extend
     
         X509Certificate[] issuerCerts = SecurityUtils.getCertificates(crypto, user);
         
-        String sigAlgo = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1;
+        String sigAlgo = defaultSigAlgo;
         String pubKeyAlgo = issuerCerts[0].getPublicKey().getAlgorithm();
         if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
             sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
@@ -116,7 +126,7 @@ public class XmlSigOutInterceptor extend
         transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
         transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
         
-        sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1, referenceId, null);
+        sig.addDocument("", transforms, digestAlgo, referenceId, null);
         
         sig.addKeyInfo(issuerCerts[0]);
         sig.addKeyInfo(issuerCerts[0].getPublicKey());