[jboss-svn-commits] JBL Code SVN: r23518 - in labs/jbossesb/branches/JBESB_4_4_GA_CP/product: install/conf and 11 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Oct 20 05:08:17 EDT 2008


Author: beve
Date: 2008-10-20 05:08:16 -0400 (Mon, 20 Oct 2008)
New Revision: 23518

Added:
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java
Modified:
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.odt
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.pdf
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java
   labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml
Log:
Work for https://jira.jboss.org/jira/browse/JBESB-2121 "Replace crypto util with sealed object"


Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.odt
===================================================================
(Binary files differ)

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.pdf
===================================================================
(Binary files differ)

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml	2008-10-20 09:08:16 UTC (rev 23518)
@@ -40,13 +40,15 @@
     <properties name="security">
         <property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
         <property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
+        
+        <!-- Algorithm and key size for internal sealing of objects -->
+        <property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+    	<property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
+    	
+        <!-- Timeout in milliseconds. After which the context is considered invalid -->
+    	<property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
 
-		<property name="org.jboss.soa.esb.services.security.privateKeystore" value="/privateKeyStore"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
-		<property name="org.jboss.soa.esb.services.security.privateKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
-    	
+		<!-- Public keystore configuration used to hold keys for encryption/decryption -->
     	<property name="org.jboss.soa.esb.services.security.publicKeystore" value="/publicKeyStore"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,50 +20,42 @@
  */
 package org.jboss.internal.soa.esb.services.security;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.io.Serializable;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
+import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SealedObject;
+import javax.crypto.SecretKey;
 import org.apache.log4j.Logger;
+import org.jboss.internal.soa.esb.assertion.AssertArgument;
 import org.jboss.soa.esb.common.Configuration;
 import org.jboss.soa.esb.common.Environment;
 import org.jboss.soa.esb.services.security.SecurityServiceException;
-import org.jboss.soa.esb.services.security.util.CryptoUtil;
-import org.jboss.soa.esb.util.ClassUtil;
 
 /**
+ * Util for sealing and unsealing object.
  *
  * @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
- *
  */
 public enum PrivateCryptoUtil
 {
     INSTANCE;
 
     private Logger log;
-    private Key key;
-    private PublicKey publicKey;
-    private String transformation;
+    private Cipher cipher;
+    private SecretKey secretKey;
 
     private PrivateCryptoUtil()
     {
         try
         {
             log = getLogger();
-            init();
+            initSecretKey();
         }
         catch (final Exception e)
         {
@@ -71,189 +63,130 @@
         }
     }
 
-    private void init() throws SecurityServiceException
+    /**
+     * Will create a Sealed object containing the passed in Serializable object.
+     *
+     * @param serializable The serializable object to be sealed.
+     * @return SealedObject The resulting sealed object
+     * @throws SecurityServiceException
+     * @throws IOException
+     * @throws IllegalBlockSizeException
+     */
+    public SealedObject sealObject(final Serializable serializable) throws SecurityServiceException
     {
-        String keystorePath = Configuration.getSecurityServicePrivateKeystore();
-        if (keystorePath == null)
+        AssertArgument.isNotNull(serializable, "serializable");
+        try
         {
-            log.info("No private keystore was specified in jbossesb-properites.xml. Add '" + Environment.SECURITY_SERVICE_PUBLIC_KEYSTORE + "'");
-        }
-        else
-        {
-            try
+            synchronized (cipher)
             {
-                String keystoreType = Configuration.getSecurityServicePrivateKeystoreType();
-                if (keystoreType == null)
-                {
-                    keystoreType = KeyStore.getDefaultType();
-                }
-                String keystorePassword = Configuration.getSecurityServicePrivateKeystorePassword();
-                String privateKeyAlias = Configuration.getSecurityServicePrivateKeyAlias();
-                String privateKeyPass = Configuration.getSecurityServicePrivateKeyPassword();
-
-                try
-                {
-                    KeyStore keystore = KeyStore.getInstance(keystoreType);
-                    InputStream in = ClassUtil.getResourceAsStream(keystorePath, this.getClass());
-                    if (in == null)
-                    {
-                        throw new SecurityServiceException("Could not locate public keystore using '" + keystorePath + "'");
-                    }
-
-                    // load the keystore contents
-                    keystore.load(in, keystorePassword.toCharArray());
-                    key = keystore.getKey(privateKeyAlias, privateKeyPass.toCharArray());
-                    Certificate certificate = keystore.getCertificate(privateKeyAlias);
-                    publicKey = certificate.getPublicKey();
-
-                    // "algorithm/mode/padding" or defaults to "algorithm"
-                    transformation = Configuration.getSecurityServicePrivateKeyTransformation();
-                    if (transformation == null)
-                    {
-                        this.transformation = key.getAlgorithm();
-                    }
-                }
-                finally
-                {
-                    keystorePassword = null;
-                    privateKeyAlias = null;
-                    privateKeyPass = null;
-                }
+                cipher.init(Cipher.ENCRYPT_MODE, secretKey);;
+                return new SealedObject(serializable, cipher);
             }
-            catch (final KeyStoreException e)
-            {
-                throw new SecurityServiceException(e.getMessage(), e);
-            }
-            catch (final NoSuchAlgorithmException e)
-            {
-                throw new SecurityServiceException(e.getMessage(), e);
-            }
-            catch (final CertificateException e)
-            {
-                throw new SecurityServiceException(e.getMessage(), e);
-            }
-            catch (final IOException e)
-            {
-                throw new SecurityServiceException(e.getMessage(), e);
-            }
-            catch (final UnrecoverableKeyException e)
-            {
-                throw new SecurityServiceException(e.getMessage(), e);
-            }
         }
-    }
-
-    private static byte[] getBytes(final Serializable ser) throws IOException
-    {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        ObjectOutputStream oout = new ObjectOutputStream(bout);
-        oout.writeObject(ser);
-        return bout.toByteArray();
-    }
-
-    public byte[] encrypt(final Serializable object) throws SecurityServiceException
-    {
-        ByteArrayInputStream plainInStream;
-        try
+        catch (final InvalidKeyException e)
         {
-            plainInStream = new ByteArrayInputStream(getBytes(object));
+            throw new SecurityServiceException(e.getMessage(), e);
         }
-        catch (final IOException e)
+        catch (final IllegalBlockSizeException e)
         {
             throw new SecurityServiceException(e.getMessage(), e);
         }
-
-        ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
-
-        try
-        {
-            byte[] buf = new byte[100];
-            int bufLength;
-            while ( (bufLength = plainInStream.read(buf)) != -1)
-            {
-                byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength),publicKey, transformation);
-                encryptedOutStream.write(tmp);
-                encryptedOutStream.flush();
-            }
-            return encryptedOutStream.toByteArray();
-        }
         catch (final IOException e)
         {
             throw new SecurityServiceException(e.getMessage(), e);
         }
     }
 
-    public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
+    /**
+     * Unseals a previously sealed object.
+     *
+     * @param sealedObject The object to unseal
+     * @return {@link Serializable} The unsealed Serializeable Object.
+     * @throws SecurityServiceException
+     */
+    public Serializable unSealObject(SealedObject sealedObject) throws SecurityServiceException
     {
-        ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
-
-        ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
-
-        byte[] decryptBytes = null;
+        AssertArgument.isNotNull(sealedObject, "sealedObject");
         try
         {
-            byte[] buf = new byte[128];
-            int bufLenth;
-            while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
+            synchronized (cipher)
             {
-                byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
-                decryptedBytesOutStream.write(tmp);
-                decryptedBytesOutStream.flush();
-                decryptBytes = decryptedBytesOutStream.toByteArray();
+                cipher.init(Cipher.DECRYPT_MODE, secretKey);
+                return (Serializable) sealedObject.getObject(cipher);
             }
         }
-        catch (final IOException e)
+        catch (final InvalidKeyException e)
         {
             throw new SecurityServiceException(e.getMessage(), e);
         }
-        finally
+        catch (final IllegalBlockSizeException e)
         {
-            try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
+            throw new SecurityServiceException(e.getMessage(), e);
         }
-
-        return toSerializable(decryptBytes);
-    }
-
-    private Serializable toSerializable(final byte[] decryptBytes) throws SecurityServiceException
-    {
-        ObjectInputStream inputStream = null;
-        try
+        catch (final BadPaddingException e)
         {
-            inputStream = new ObjectInputStream(new ByteArrayInputStream(decryptBytes));
-            return (Serializable) inputStream.readObject();
+            throw new SecurityServiceException(e.getMessage(), e);
         }
-        catch (final IOException e)
+        catch (IOException e)
         {
             throw new SecurityServiceException(e.getMessage(), e);
         }
-        catch (final ClassNotFoundException e)
+        catch (ClassNotFoundException e)
         {
             throw new SecurityServiceException(e.getMessage(), e);
         }
-        finally
-        {
-            try { inputStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(), ignore); }
-        }
     }
 
-    private static byte[] copyBytes(byte[] bytes, int length)
+    /**
+     * Generates a symmetric key used for sealing object.
+     *
+     * @throws SecurityServiceException
+     */
+    private void initSecretKey() throws SecurityServiceException
     {
-        if (bytes.length == length)
+        try
         {
-            return bytes;
-        }
+            final String algorithm = Configuration.getSecurityServiceSealAlgorithm();
+            if (algorithm == null)
+            {
+                throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_ALGORITHM + "' has not been configured. Please set the algorithm to use in jbossesb-properties.xml");
+            }
 
-        byte[] newBytes = new byte[length];
-        for (int i = 0; i < length; i++)
+            final String keySizeStr = Configuration.getSecurityServiceSealKeySize();
+            if (keySizeStr == null)
+            {
+                throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_KEYSIZE + "' has not been configured. Please set the key size to use in jbossesb-properties.xml");
+            }
+
+            int keySize;
+            try
+            {
+                keySize = Integer.parseInt(keySizeStr.trim());
+            }
+            catch(final NumberFormatException e)
+            {
+                throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_KEYSIZE + "' must be a number. Please set the key size correctly in jbossesb-properties.xml");
+            }
+
+            log.debug("SealAlgorithm '" + algorithm + "' keySize '" + keySize + "'");
+
+            final KeyGenerator kpg = KeyGenerator.getInstance(algorithm);
+            kpg.init(keySize);
+            secretKey = kpg.generateKey();
+            cipher = Cipher.getInstance(algorithm);
+        }
+        catch (final NoSuchAlgorithmException e)
         {
-            newBytes[i] = bytes[i];
+            throw new SecurityServiceException(e.getMessage(), e);
         }
-        return newBytes;
+        catch (final NoSuchPaddingException e)
+        {
+            throw new SecurityServiceException(e.getMessage(), e);
+        }
     }
 
     private static Logger getLogger()
     {
         return Logger.getLogger(PrivateCryptoUtil.class);
     }
-
 }

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -19,18 +19,15 @@
  */
 package org.jboss.soa.esb.client;
 
-import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
 import javax.crypto.SealedObject;
-import javax.security.auth.Subject;
 
 import org.apache.log4j.Logger;
 import org.jboss.internal.soa.esb.addressing.helpers.EPRHelper;
 import org.jboss.internal.soa.esb.assertion.AssertArgument;
-import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
 import org.jboss.soa.esb.ConfigurationException;
 import org.jboss.soa.esb.Service;
 import org.jboss.soa.esb.addressing.EPR;
@@ -43,9 +40,9 @@
 import org.jboss.soa.esb.couriers.Courier;
 import org.jboss.soa.esb.couriers.CourierException;
 import org.jboss.soa.esb.couriers.CourierFactory;
+import org.jboss.soa.esb.couriers.CourierMarshalUnmarshalException;
+import org.jboss.soa.esb.couriers.CourierServiceBindException;
 import org.jboss.soa.esb.couriers.CourierTransportException;
-import org.jboss.soa.esb.couriers.CourierServiceBindException;
-import org.jboss.soa.esb.couriers.CourierMarshalUnmarshalException;
 import org.jboss.soa.esb.couriers.CourierUtil;
 import org.jboss.soa.esb.couriers.FaultMessageException;
 import org.jboss.soa.esb.couriers.TwoWayCourier;
@@ -63,7 +60,7 @@
 import org.jboss.soa.esb.services.registry.ServiceNotFoundException;
 import org.jboss.soa.esb.services.security.SecurityContext;
 import org.jboss.soa.esb.services.security.SecurityService;
-import org.jboss.soa.esb.services.security.SecurityServiceException;
+import org.jboss.soa.esb.services.security.auth.AuthenticationRequestImpl;
 import org.jboss.soa.esb.util.ClassUtil;
 
 /**
@@ -290,6 +287,28 @@
     private Message post(Message message, EPRInvoker eprInvoker) throws MessageDeliverException, FaultMessageException {
         boolean staleEPRCache = true;
         boolean initialPass = true;
+
+        /*
+         * Re-attach encrypted SecurityContext to outgoing message.
+         */
+        final SealedObject sealedObject = SecurityContext.getSecurityContext();
+        if (sealedObject != null)
+        {
+            message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
+            // clear the security context from the thread local.
+            SecurityContext.setSecurityContext(null);
+        }
+        /*
+         * Re-attach encrypted AuthenticationRequest to outgoing message.
+         */
+        final byte[] encryptedAuthRequest = AuthenticationRequestImpl.getEncryptedAuthRequest();
+        if (encryptedAuthRequest != null)
+        {
+            message.getContext().setContext(SecurityService.AUTH_REQUEST, encryptedAuthRequest);
+            // clear the auth request from the thread local.
+            AuthenticationRequestImpl.setEncryptedAuthRequest(null);
+        }
+
         //We are removing dead EPRs from the serviceClusterInfo. *Previous* deliveries maybe have
         //removed EPRs that have now come back to life. We should try once more to pull a fresh list of EPRS
         //from the registry before we give up (and fail-over to redelivery at a later time in the care
@@ -323,25 +342,11 @@
             while ((epr = loadBalancer.chooseEPR(serviceClusterInfo)) != null) {
             	try
             	{
-            	    final Subject subject = Subject.getSubject(AccessController.getContext());
-            	    if (subject != null)
-            	    {
-            	        logger.info("Subject in ServiceInvoker " + subject);
-                        try
-                        {
-                			byte[] encrypted = PrivateCryptoUtil.INSTANCE.encrypt(new SecurityContext(subject));
-                    	    message.getContext().setContext(SecurityService.CONTEXT, encrypted);
-                        }
-                        catch (final SecurityServiceException e)
-                        {
-                            logger.error("Could not encrypt the security conext. Will not be added to the outgoing message", e);
-                        }
-            	    }
-
 	                replyMessage = eprInvoker.attemptDelivery(message, epr);
 	                if (replyMessage != null) {
                         // remove the security context so that it is not exposed to the action pipeline.
                         replyMessage.getContext().removeContext(SecurityService.CONTEXT);
+                        replyMessage.getContext().removeContext(SecurityService.AUTH_REQUEST);
 
                         if (Type.isFaultMessage(replyMessage)) {
                             Factory.createExceptionFromFault(replyMessage) ;

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -534,6 +534,21 @@
 		return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_CALLBACK_HANLDER_CLASS);
 	}
 
+	public static String getSecurityServiceSealAlgorithm()
+	{
+		return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_SEAL_ALGORITHM);
+	}
+
+	public static String getSecurityServiceSealKeySize()
+	{
+		return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_SEAL_KEYSIZE);
+	}
+
+	public static String getSecurityServiceContextTimeout()
+	{
+		return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+	}
+
 	public static Properties getSecurityServiceProperies()
 	{
 		return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperties();

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -230,6 +230,7 @@
 	public static final String SECURITY_SERVICE_CONFIG_URL 				= "org.jboss.soa.esb.services.security.configUrl";
 	public static final String SECURITY_SERVICE_SEAL_ALGORITHM 			= "org.jboss.soa.esb.services.security.sealAlgorithm";
 	public static final String SECURITY_SERVICE_SEAL_KEYSIZE 			= "org.jboss.soa.esb.services.security.sealKeySize";
+	public static final String SECURITY_SERVICE_CONTEXT_TIMEOUT			= "org.jboss.soa.esb.services.security.contextTimeout";
 
 	public static final String SECURITY_SERVICE_PRIVATE_KEYSTORE		= "org.jboss.soa.esb.services.security.privateKeystore";
 	public static final String SECURITY_SERVICE_PRIVATE_KEYSTORE_TYPE	= "org.jboss.soa.esb.services.security.privateKeystoreType";

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,10 +22,12 @@
 
 package org.jboss.soa.esb.listeners.message;
 
+import java.net.URISyntaxException;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import javax.crypto.SealedObject;
 import javax.security.auth.Subject;
 import javax.xml.validation.Schema;
 
@@ -43,6 +45,7 @@
 import org.jboss.soa.esb.addressing.util.DefaultFaultTo;
 import org.jboss.soa.esb.addressing.util.DefaultReplyTo;
 import org.jboss.soa.esb.client.ServiceInvoker;
+import org.jboss.soa.esb.common.Environment;
 import org.jboss.soa.esb.couriers.Courier;
 import org.jboss.soa.esb.couriers.CourierException;
 import org.jboss.soa.esb.couriers.CourierFactory;
@@ -62,6 +65,7 @@
 import org.jboss.soa.esb.services.security.SecurityServiceException;
 import org.jboss.soa.esb.services.security.SecurityServiceFactory;
 import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
+import org.jboss.soa.esb.services.security.auth.AuthenticationRequestImpl;
 import org.jboss.soa.esb.util.ClassUtil;
 import org.xml.sax.SAXException;
 
@@ -71,6 +75,7 @@
  * @author <a
  *         href="mailto:schifest at heuristica.com.ar">schifest at heuristica.com.ar</a>
  * @author kevin
+ * @author <a href="mailto:dbevenius at jboss.com">Daniel Bevenius</a>
  * @since Version 4.0
  */
 public class ActionProcessingPipeline
@@ -367,32 +372,11 @@
 				LOGGER.debug("pipeline process for message: "+message.getHeader());
 			}
 
-			SecurityContext securityContext = null;
-			try
-            {
-			    // Check if a encrypted SecurityContext was passed with the Message to this service.
-                securityContext = SecurityContext.decryptContext((byte[])message.getContext().getContext(SecurityService.CONTEXT));
-            }
-			catch (final SecurityServiceException e)
-            {
-			    LOGGER.debug("Security exception: ", e);
-			    // just make sure the securityContext is null. This will trigger a new auth if security is enabled.
-			    securityContext = null;
-            }
-
-			if (securityConf != null || securityContext != null)
-			{
-				return processPipelineSecured(message, securityContext);
-			}
-			else
-			{
-    			return processPipeline(message);
-			}
+			return processPipeline(message, getSecurityContext(message));
 		}
 		else
 		{
-    		final Call callDetails = new Call() ;
-    		callDetails.copy(message.getHeader().getCall()) ;
+    		final Call callDetails = createCallDetails(message);
 			LOGGER.debug("pipeline process disabled for message: "+message.getHeader());
 
 			faultTo(callDetails, Factory.createErrorMessage(Factory.NOT_ENABLED, message, null));
@@ -404,40 +388,95 @@
 		}
 	}
 
-	private boolean processPipelineSecured(final Message message, SecurityContext securityContext)
+	/**
+	 * Processes the action pipeline.
+	 * <p/>
+	 * If the service has been enable for security authentication, it has the security element
+	 * in the configuration xml that is, this method will authenitcate the caller.
+	 * If security has not been enabled this method will not perform any authentication but
+	 * it will pass through a pre-existing SecurityContext.
+	 * <p>
+	 * <h1>SecurityContext</h1>
+	 * After the caller has been successfully authenticated a SecurityContext will be created.
+	 * This context is valid on the current ESB node(VM) only. When a SecurityContext is created
+	 * a timeout is specified. This value can either be the globally value specified in jbossesb-properties.xml
+	 * or it can be overridden per service by specifiying the same property in the security element in jboss-esb.xml:
+	 * The value is specified in milliseconds.
+	 * <pre>
+	 *     <security module="someModuleName">
+	 *         <property name="org.jboss.soa.esb.services.security.contextTimeout" value="50000"/>
+	 *     </security>
+	 * </pre>
+	 * <h1>AuthenticationRequest</h1>
+	 * If a call is routed to a different ESB node then that node will re-authenticate the call.
+	 * The node will descrypt the authentication request passed with the Message object
+	 * and try to authenticate the caller.
+	 *
+	 * @param message The ESB message object.
+	 * @param sealedSecurityContext The sealed SecurityContext which will exist if the caller has already been authenticated.
+	 * @return true If the action pipeline was processed successfully.
+	 */
+	private boolean processPipeline(final Message message, final SealedObject sealedSecurityContext)
 	{
-		final Call callDetails = new Call() ;
-		callDetails.copy(message.getHeader().getCall()) ;
+		SecurityContext securityContext = null;
 
+		if (sealedSecurityContext != null )
+        {
+    		// store the security context. Will be re-attached to outgoing messages regardless whether the service is secured or not.
+            SecurityContext.setSecurityContext(sealedSecurityContext);
+        }
+
 		try
 		{
-		    // always perform authentication if the service is security enabled.
-		    if (securityConf != null )
+		    if (isServiceSecured())
 		    {
-		        if (securityContext == null)
+		        try // to decrypt the security context.
+                {
+                    securityContext = SecurityContext.decryptContext(sealedSecurityContext);
+                }
+                catch (final SecurityServiceException ignored)
+                {
+                    LOGGER.debug("Could not decrypt the security context. Might have come from a different VM. Will re-authenticate if security is enabled for this service.", ignored);
+                    securityContext = null;
+                }
+
+                if (LOGGER.isDebugEnabled())
+                {
+                    if (securityContext != null)
+                    {
+                        /*
+                         * Might be interesting to know if a security context is often invalid as this
+                         * will cause re-authentication. This might be avoidable by setting a longer
+                         * timeout by overriding the default timeout(jbossesb-properties.xml) and specifying
+                         * one on the security element in jboss-esb.xml.
+                         */
+        		        LOGGER.debug(securityContext);
+                    }
+                }
+
+    			final SecurityService securityService = SecurityServiceFactory.getSecurityService();
+
+		        if (securityContext == null || !securityContext.isValid())
 		        {
-		            // no existing security context exist. Create one to drive the autentication.
-    		        securityContext = new SecurityContext();
+        			// get the encrypted AuthenticationRequest from the message
+            		final byte[] encryptedAuthRequest = getAutenticationRequest(message);
+            		final AuthenticationRequest authRequest = (AuthenticationRequest) PublicCryptoUtil.INSTANCE.decrypt(encryptedAuthRequest);
 
-        			// 	get the authentication request from the message
-            		byte[] encrypted = (byte[]) message.getContext().getContext(SecurityService.AUTH_REQUEST);
-            		if (encrypted == null)
-            		{
-            		   throw new SecurityServiceException("Missing AuthenticationRequest. Cannot be authenticated.");
-            		}
-            		AuthenticationRequest authRequest = (AuthenticationRequest) PublicCryptoUtil.INSTANCE.decrypt(encrypted);
+            		// store the encrypted auth request. Will be re-attached to outgoing messages.
+            		AuthenticationRequestImpl.setEncryptedAuthRequest(encryptedAuthRequest);
 
-            		//  authenticate the caller
-        			SecurityServiceFactory.getSecurityService().authenticate(securityConf, securityContext, authRequest);
+		             // no existing security context exist or it had expired. Create a new one to drive the autentication.
+    		        securityContext = new SecurityContext(new Subject(), getSecurityContextTimeout(securityConf));
+
+            		// authenticate the caller
+        			securityService.authenticate(securityConf, securityContext, authRequest);
+
+            		// store the encrypted security context. Will be re-attached to outgoing messages.
+        			SecurityContext.setSecurityContext(SecurityContext.encryptContext(securityContext));
 		        }
-		        /*
-		         * The SecurityContext was not null so we were able to decrypt the security context
-		         * and this is a valid authenticated request and re-authentication is not done.
-		         */
 
-		        // check the allowed roles if configured.
-        		boolean checkRolesAllowed = SecurityServiceFactory.getSecurityService().checkRolesAllowed(securityConf.getRolesAllowed(), securityContext);
-        		if (!checkRolesAllowed)
+		        // check that the caller is a member of atleast on of the declared roles.
+        		if (!securityService.checkRolesAllowed(securityConf.getRolesAllowed(), securityContext))
         		{
         			throw new SecurityServiceException("Caller did not belong to any of the rolesAllowed " + securityConf.getRolesAllowed());
         		}
@@ -445,14 +484,14 @@
 		}
 		catch (final SecurityServiceException e)
 		{
-			LOGGER.debug( "SecurityService exception : ", e);
-			faultTo(callDetails, Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
+			LOGGER.error( "SecurityService exception : ", e);
+			faultTo(createCallDetails(message), Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
 			return false;
 		}
 		catch (final ConfigurationException e)
 		{
-			LOGGER.debug( "SecurityService exception : ", e);
-			faultTo(callDetails, Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
+			LOGGER.error( "SecurityService exception : ", e);
+			faultTo(createCallDetails(message), Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
 			return false;
 		}
 		finally
@@ -462,25 +501,20 @@
     		message.getContext().removeContext(SecurityService.AUTH_REQUEST);
 		}
 
-		// the work to be performed in the context of the authenticated caller
-		PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>()
+		if (securityContext != null)
 		{
-			public Boolean run()
-			{
-				return processPipeline(message);
-			}
-		};
-
-		Boolean processResult = (Boolean)Subject.doAsPrivileged(securityContext.getSubject(), action, null);
-
-		return processResult.booleanValue();
+    		return (Boolean) Subject.doAsPrivileged(securityContext.getSubject(), getPrivilegedAction(message), null);
+		}
+		else
+		{
+		    return processPipeline(message);
+		}
 	}
 
 	private boolean processPipeline(final Message message)
 	{
 		final long start = System.nanoTime();
-		final Call callDetails = new Call() ;
-		callDetails.copy(message.getHeader().getCall()) ;
+		final Call callDetails = createCallDetails(message);
 
 			if (LOGGER.isDebugEnabled())
 			{
@@ -836,4 +870,79 @@
 		}
 	}
 
+    private boolean isServiceSecured()
+    {
+        return securityConf != null;
+    }
+
+    private byte[] getAutenticationRequest(final Message message) throws SecurityServiceException
+    {
+        final byte[] encryptedAuthRequest = (byte[]) message.getContext().getContext(SecurityService.AUTH_REQUEST);
+        if (encryptedAuthRequest == null)
+        {
+           throw new SecurityServiceException("Missing AuthenticationRequest. Cannot be authenticated.");
+        }
+        return encryptedAuthRequest;
+    }
+
+    private SealedObject getSecurityContext(final Message message)
+    {
+        return (SealedObject) message.getContext().getContext(SecurityService.CONTEXT);
+    }
+
+    private PrivilegedAction<Boolean> getPrivilegedAction(final Message message)
+    {
+        // the work to be performed in the context of the authenticated caller
+        return new PrivilegedAction<Boolean>()
+        {
+            public Boolean run()
+            {
+                return processPipeline(message);
+            }
+        };
+    }
+
+    @SuppressWarnings("deprecation")
+    private Call createCallDetails(final Message message)
+    {
+        Call callDetails;
+        try
+        {
+            callDetails = new Call(message.getHeader().getCall());
+        }
+        catch (final URISyntaxException e)
+        {
+            LOGGER.error("Caught an URISyntaxException while calling Call's copy constructor. Will revert to using the old way using the copy method.", e);
+            callDetails = new Call();
+    		callDetails.copy(message.getHeader().getCall()) ;
+        }
+        return callDetails;
+    }
+
+    /**
+     * Checks if the security config as a property named 'org.jboss.soa.esb.services.security.contextTimeout'
+     * specified. This will in that case be used as the SecurityContext timeout for this pipeline.
+     * If not specified the value will fallback to the value specified in jbossesb-properties.xml
+     *
+     * @param securityConfig The security configuration for this pipeline. This maps to the security element in jboss-esb.xml
+     * @return long Either the timeout value specified in the security element in jboss-esb.xml otherwise the value in jbossesb-properties.xml
+     * @throws SecurityServiceException If the value specified in jbossesb-properties.xml cannot be parsed. If the value in jboss-esb.xml cannot be parsed, only a warning will be issued.
+     */
+    long getSecurityContextTimeout(final SecurityConfig securityConfig) throws SecurityServiceException
+    {
+        String timeoutStr = securityConfig.getProperties().get(Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+        if (timeoutStr != null)
+        {
+            try
+            {
+                return Long.parseLong(timeoutStr);
+            }
+            catch (final NumberFormatException ignore)
+            {
+                LOGGER.warn("Could not parse '" + timeoutStr +"' to a long. Please make sure the the value of the property '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' in jbossesb-xml is a valid long(ms)");
+               // fallback to global configuration.
+            }
+        }
+        return SecurityContext.getConfigurationTimeout();
+    }
 }

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -44,6 +44,7 @@
 import org.jboss.soa.esb.util.ClassUtil;
 
 /**
+ * Util for encrypting/decrypting using assymmetric keys.
  *
  * @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
  *
@@ -71,6 +72,78 @@
         }
     }
 
+    public byte[] encrypt(final Serializable object) throws SecurityServiceException
+    {
+        if (!isSecurityConfigured)
+        {
+            return null;
+        }
+    
+        ByteArrayInputStream plainInStream;
+        try
+        {
+            plainInStream = new ByteArrayInputStream(getBytes(object));
+        }
+        catch (final IOException e)
+        {
+            throw new SecurityServiceException(e.getMessage(), e);
+        }
+    
+        ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
+    
+        try
+        {
+            byte[] buf = new byte[100];
+            int bufLength;
+            while ( (bufLength = plainInStream.read(buf)) != -1)
+            {
+                byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength), publicKey, transformation);
+                encryptedOutStream.write(tmp);
+                encryptedOutStream.flush();
+            }
+            return encryptedOutStream.toByteArray();
+        }
+        catch (final IOException e)
+        {
+            throw new SecurityServiceException(e.getMessage(), e);
+        }
+    }
+
+    public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
+    {
+        if (!isSecurityConfigured)
+        {
+            return null;
+        }
+        ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
+    
+        ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
+    
+        byte[] decryptBytes = null;
+        try
+        {
+            byte[] buf = new byte[128];
+            int bufLenth;
+            while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
+            {
+                byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
+                decryptedBytesOutStream.write(tmp);
+                decryptedBytesOutStream.flush();
+                decryptBytes = decryptedBytesOutStream.toByteArray();
+            }
+        }
+        catch (final IOException e)
+        {
+            throw new SecurityServiceException(e.getMessage(), e);
+        }
+        finally
+        {
+            try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
+        }
+    
+        return toSerializable(decryptBytes);
+    }
+
     private void init() throws SecurityServiceException
     {
         String keystorePath = Configuration.getSecurityServicePublicKeystore();
@@ -152,78 +225,6 @@
         return bout.toByteArray();
     }
 
-    public byte[] encrypt(final Serializable object) throws SecurityServiceException
-    {
-        if (!isSecurityConfigured)
-        {
-            return null;
-        }
-
-        ByteArrayInputStream plainInStream;
-        try
-        {
-            plainInStream = new ByteArrayInputStream(getBytes(object));
-        }
-        catch (final IOException e)
-        {
-            throw new SecurityServiceException(e.getMessage(), e);
-        }
-
-        ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
-
-        try
-        {
-            byte[] buf = new byte[100];
-            int bufLength;
-            while ( (bufLength = plainInStream.read(buf)) != -1)
-            {
-                byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength),publicKey, transformation);
-                encryptedOutStream.write(tmp);
-                encryptedOutStream.flush();
-            }
-            return encryptedOutStream.toByteArray();
-        }
-        catch (final IOException e)
-        {
-            throw new SecurityServiceException(e.getMessage(), e);
-        }
-    }
-
-    public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
-    {
-        if (!isSecurityConfigured)
-        {
-            return null;
-        }
-        ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
-
-        ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
-
-        byte[] decryptBytes = null;
-        try
-        {
-            byte[] buf = new byte[128];
-            int bufLenth;
-            while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
-            {
-                byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
-                decryptedBytesOutStream.write(tmp);
-                decryptedBytesOutStream.flush();
-                decryptBytes = decryptedBytesOutStream.toByteArray();
-            }
-        }
-        catch (final IOException e)
-        {
-            throw new SecurityServiceException(e.getMessage(), e);
-        }
-        finally
-        {
-            try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
-        }
-
-        return toSerializable(decryptBytes);
-    }
-
     private Serializable toSerializable(final byte[] decryptBytes) throws SecurityServiceException
     {
         ObjectInputStream inputStream = null;

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,9 +22,6 @@
 
 import static org.jboss.soa.esb.services.security.principals.Group.ROLES_GROUP_NAME;
 
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.security.Principal;
 import java.security.acl.Group;
@@ -32,20 +29,28 @@
 import java.util.Enumeration;
 import java.util.Set;
 
+import javax.crypto.SealedObject;
 import javax.security.auth.Subject;
 
 import org.jboss.internal.soa.esb.assertion.AssertArgument;
 import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
+import org.jboss.soa.esb.common.Configuration;
+import org.jboss.soa.esb.common.Environment;
 import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
-import org.mvel.ast.AssertNode;
 
 /**
  * Security Context contains security related information.
  * <p/>
+ *
  * Note that even though a Subject object instance is serialiable,
  * its private and public credentials are not(they are transient).
+ * <p>
  * Also not that the Principal interface is not serializable but
  * all implemenations should be.
+ * <p>
+ * When created a SecurityContext will be given a timeout argument which
+ * is the time in milliseconds after which the context is considered
+ * invalid.
  *
  * @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
  * @since 4.4
@@ -55,34 +60,43 @@
 {
 	private static final long serialVersionUID = 1L;
 
+	private static transient ThreadLocal<SealedObject> securityContextTl = new ThreadLocal<SealedObject>();
+
+	private static long globalConfiguredTimeout;
+
+	/**
+	 * The Subject associated with this context.
+	 */
 	private final Subject subject;
 
-    private Set<?> pubCredentials;
+    /**
+     * Timeout (ms) for the security context. Defaults to 5 mins.
+     */
+    private long timeout = 30000;
 
-    private Set<?> privCredentials;
+    /**
+     * Time of creation.
+     */
+    private long timeOfCreation = System.currentTimeMillis();
 
-	public SecurityContext()
+	/**
+	 * Creates a SecurityContext associating the passed in Subject with it.
+	 *
+	 * @param subject The Subject that is to be associated with this security context.
+	 * @param timeout A timeout which specifies how long this Security Context is valid for. Must be a positiv value.
+	 */
+	public SecurityContext(final Subject subject, final long timeout)
 	{
-		subject = new Subject();
-	}
-
-	public SecurityContext(Subject subject)
-	{
 	    AssertArgument.isNotNull(subject, "subject");
 		this.subject = subject;
-	}
 
-	public Subject getSubject()
-	{
-		return subject;
+	    if ( timeout < -1 )
+	    {
+	        throw new IllegalArgumentException("'timeout' for SecurityContext must not be negative other then '-1' which indicates a SecurityContext that never expires.");
+	    }
+        this.timeout = timeout;
 	}
 
-	@Override
-    public String toString()
-	{
-		return "SecurityContext [" + subject + "]";
-	}
-
 	public boolean isCallerInRole( final String roleName )
 	{
         Set<Principal> principals = subject.getPrincipals();
@@ -108,35 +122,6 @@
         return false;
 	}
 
-	private void writeObject(final ObjectOutputStream out) throws IOException
-	{
-	   out.defaultWriteObject();
-	   out.writeObject(subject.getPrivateCredentials());
-	   out.writeObject(subject.getPublicCredentials());
-	}
-
-	private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
-	{
-	   in.defaultReadObject();
-	   privCredentials = (Set<?>) in.readObject();
-	   pubCredentials = (Set<?>) in.readObject();
-	}
-
-	final Set<? extends Principal> getPrincipals()
-	{
-		return Collections.unmodifiableSet(subject.getPrincipals());
-	}
-
-    final Set<?> getPubCredentials()
-    {
-        return Collections.unmodifiableSet(pubCredentials);
-    }
-
-    public Set<?> getPrivCredentials()
-    {
-        return Collections.unmodifiableSet(privCredentials);
-    }
-
     /**
      * Will check if the passed in {@link AuthenticationRequest} contains the
      * same security information (Principal and credentials) as the this context.
@@ -176,38 +161,114 @@
                 }
             }
         }
-
         return false;
     }
 
-    public static SecurityContext decryptContext(final byte[] encrypt) throws SecurityServiceException
+    public long getTimeOfCreation()
     {
+        return timeOfCreation;
+    }
+
+    /**
+     * Timeout if milliseconds.
+     *
+     * @return long The timeout (ms) for this security context.
+     */
+    public long getTimeout()
+    {
+        return timeout;
+    }
+
+    public boolean isValid()
+    {
+        if ( timeout == -1 )
+        {
+            return true;
+        }
+
+        return timeOfCreation + timeout > System.currentTimeMillis();
+    }
+
+    public Subject getSubject()
+    {
+    	return subject;
+    }
+
+    @Override
+    public String toString()
+    {
+    	return "SecurityContext [isValid " + isValid() + ", timeout :" + timeout + ", timeOfCreation : " + timeOfCreation + "]";
+    }
+
+    //  package protected methods
+
+    final Set<? extends Principal> getPrincipals()
+    {
+    	return Collections.unmodifiableSet(subject.getPrincipals());
+    }
+
+    //  static methods
+
+    public static SecurityContext decryptContext(final SealedObject sealedObject) throws SecurityServiceException
+    {
+        if (sealedObject == null)
+            return null;
+
         SecurityContext context = null;
-        if (encrypt == null)
-            return context;
-
-        Serializable decrypted = PrivateCryptoUtil.INSTANCE.decrypt(encrypt);
+        Serializable decrypted = PrivateCryptoUtil.INSTANCE.unSealObject(sealedObject);
         if (decrypted instanceof SecurityContext)
         {
            context = (SecurityContext) decrypted;
-           final Subject subject = context.getSubject();
-           final Set<?> publCreds = context.getPubCredentials();
-           if (publCreds != null )
-           {
-               subject.getPublicCredentials().addAll(publCreds);
-           }
-           final Set<?> privCreds = context.getPrivCredentials();
-           if (privCreds != null)
-           {
-               subject.getPrivateCredentials().addAll(privCreds);
-           }
         }
         return context;
     }
 
-    public static byte[] encryptContext(final SecurityContext context) throws SecurityServiceException
+    public static SealedObject encryptContext(final SecurityContext context) throws SecurityServiceException
     {
-        return PrivateCryptoUtil.INSTANCE.encrypt(context);
+        return PrivateCryptoUtil.INSTANCE.sealObject(context);
     }
 
+    /**
+     * Get the globally configured security context timeout.
+     * @return
+     * @throws SecurityServiceException
+     */
+    public static long getConfigurationTimeout() throws SecurityServiceException
+    {
+        if (globalConfiguredTimeout == 0l)
+        {
+            globalConfiguredTimeout = getGlobalConfigurationTimeout();
+        }
+        return globalConfiguredTimeout;
+    }
+
+    public static void setSecurityContext(final SealedObject sealedObject)
+    {
+        SecurityContext.securityContextTl.set(sealedObject);
+    }
+
+    public static SealedObject getSecurityContext()
+    {
+        return SecurityContext.securityContextTl.get();
+    }
+
+    private static long getGlobalConfigurationTimeout() throws SecurityServiceException
+    {
+        final String timeoutStr = Configuration.getSecurityServiceContextTimeout();
+        if (timeoutStr == null)
+        {
+            throw new SecurityServiceException("No timeout was configured for the security context. Please set the value of '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' to the timeout you desire");
+        }
+        else
+        {
+           try
+           {
+               return Long.parseLong(timeoutStr.trim());
+           }
+           catch(final NumberFormatException e)
+           {
+                throw new SecurityServiceException("The value of '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' must be specified as a long");
+           }
+        }
+    }
 }

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,6 +41,8 @@
 {
 	private static final long serialVersionUID = 1L;
 
+	private static transient ThreadLocal<byte[]> encryptedAuthRequest = new ThreadLocal<byte[]>();
+
 	private Principal principal;
 	private Set<?> credentials;
 	private Map<String,?> properties;
@@ -69,7 +71,17 @@
 		return principal;
 	}
 
-	public static class Builder
+	public static byte[] getEncryptedAuthRequest()
+    {
+        return encryptedAuthRequest.get();
+    }
+
+    public static void setEncryptedAuthRequest(byte[] encryptedAuthRequest)
+    {
+        AuthenticationRequestImpl.encryptedAuthRequest.set(encryptedAuthRequest);
+    }
+
+    public static class Builder
 	{
     	private Principal principal;
     	private Set<Object> credentials = new HashSet<Object>();

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -21,6 +21,7 @@
 package org.jboss.soa.esb.services.security.util;
 
 import java.security.InvalidKeyException;
+import java.security.Key;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -41,7 +42,7 @@
 {
     private CryptoUtil() {}
 
-    public static byte[] decrypt(final byte[] bytes, final PrivateKey key, final String transformation) throws SecurityServiceException
+    public static byte[] decrypt(final byte[] bytes, final Key key, final String transformation) throws SecurityServiceException
     {
         try
         {
@@ -71,7 +72,7 @@
         }
     }
 
-    public static byte[] encrypt(byte[] text, PublicKey key, String transformation) throws SecurityServiceException
+    public static byte[] encrypt(byte[] text, Key key, String transformation) throws SecurityServiceException
     {
         try
         {

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,6 +22,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.net.URL;
 import java.security.Principal;
@@ -75,7 +76,7 @@
 		credentials.add(password);
 
 		AuthenticationRequest authRequest = new AuthenticationRequestImpl.Builder(principal, credentials).build();
-		SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
 		service.configure();
 		service.authenticate(configInfo, context, authRequest);
 
@@ -90,7 +91,7 @@
 		Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
 		builder.runAs("adminRole");
 		SecurityConfig configInfo = builder.build();
-		SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
 		service.authenticate(configInfo, context, null);
 		Set<Principal> principals = subject.getPrincipals( Principal.class );
 		assertEquals( 2, principals.size() );
@@ -107,7 +108,7 @@
 
 		subject.getPrincipals().add(group);
 
-		SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
 		service.authenticate(configInfo, context, null);
 
 		Set<Principal> principals = subject.getPrincipals( Principal.class );
@@ -121,7 +122,7 @@
 		Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
 		builder.runAs(roleName);
 		SecurityConfig configInfo = builder.build();
-		SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
 		service.authenticate(configInfo, context, null);
 		assertTrue( service.isCallerInRole(subject, new Role(roleName)));
 	}
@@ -131,7 +132,7 @@
 	{
 		Builder builder = new SecurityConfig.Builder("FailureLogin");
 		SecurityConfig configInfo = builder.build();
-		SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
 		service.authenticate( configInfo, context, null );
 	}
 
@@ -142,12 +143,53 @@
         builder.runAs("esbRole");
         builder.rolesAllowed("esbRole");
         SecurityConfig configInfo = builder.build();
-        SecurityContext context = new SecurityContext(subject);
+		SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
         service.authenticate( configInfo, context, null );
         boolean checkRolesAllowed = service.checkRolesAllowed(configInfo.getRolesAllowed(), context);
         assertTrue(checkRolesAllowed);
     }
 
+	@Test
+	public void refresh() throws SecurityServiceException
+	{
+		Runnable runnable = new Runnable()
+		{
+			public void run()
+			{
+				try
+                {
+                    threadLogin();
+                }
+				catch (final SecurityServiceException ignore)
+                {
+				    ignore.printStackTrace();
+                }
+			}
+		};
+		for (int i = 0; i < 1000; i++)
+		{
+    		Thread t1 = new Thread(runnable);
+    		Thread t2 = new Thread(runnable);
+    		t1.start();
+    		t2.start();
+		}
+	}
+
+	private void threadLogin() throws SecurityServiceException
+	{
+		Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
+		SecurityConfig configInfo = builder.build();
+		SecurityContext context = new SecurityContext(new Subject(), SecurityContext.getConfigurationTimeout());
+		try
+		{
+			service.authenticate( configInfo, context, null );
+		}
+		catch (SecurityServiceException e)
+		{
+    		fail(e.getMessage());
+		}
+	}
+
 	@Before
 	public void setup() throws ConfigurationException
 	{

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,17 +20,14 @@
  */
 package org.jboss.internal.soa.esb.services.security;
 
-import static org.junit.Assert.*;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import java.io.IOException;
 import java.io.Serializable;
 import java.net.URL;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Provider;
-import java.security.Security;
 
+import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.SealedObject;
 
 import junit.framework.JUnit4TestAdapter;
@@ -54,13 +51,14 @@
 	private String jbossEsbProperties;
 
     @Test
-    public void encryptAndDecrypt() throws SecurityServiceException
+    public void sealObject() throws SecurityServiceException, IllegalBlockSizeException, IOException
     {
-        String object = "some texti: dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
-        byte[] encrypted = PrivateCryptoUtil.INSTANCE.encrypt(object);
-        assertFalse(object.equals(new String(encrypted)));
+        final String object = getLongString(5000);
 
-        Serializable plainObject = PrivateCryptoUtil.INSTANCE.decrypt(encrypted);
+        final SealedObject sealedObject = PrivateCryptoUtil.INSTANCE.sealObject(object);
+        assertNotNull(sealedObject);
+
+        final Serializable plainObject = PrivateCryptoUtil.INSTANCE.unSealObject(sealedObject);
         assertEquals(object, plainObject);
     }
 
@@ -81,6 +79,16 @@
         }
     }
 
+    private String getLongString(final int size)
+    {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < size; i++)
+        {
+            sb.append(i);
+        }
+        return sb.toString();
+    }
+
     public static junit.framework.Test suite()
     {
         return new JUnit4TestAdapter(PrivateCryptoUtilUnitTest.class);

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml	2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,11 +41,11 @@
     	<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
     	<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
     	
-    	<property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+    	<property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+    	<property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
     	
+    	<property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+    	
     </properties>
     <properties name="registry">
     	<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -24,12 +24,15 @@
 
 import java.io.Serializable;
 import java.net.URL;
+import java.util.concurrent.TimeUnit;
 
+import javax.crypto.SealedObject;
 import javax.security.auth.Subject;
 
 import junit.framework.TestCase;
 
 import org.jboss.internal.soa.esb.services.registry.MockRegistry;
+import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
 import org.jboss.soa.esb.ConfigurationException;
 import org.jboss.soa.esb.common.Environment;
 import org.jboss.soa.esb.common.ModulePropertyManager;
@@ -39,6 +42,8 @@
 import org.jboss.soa.esb.message.Message;
 import org.jboss.soa.esb.message.format.MessageFactory;
 import org.jboss.soa.esb.services.security.PublicCryptoUtil;
+import org.jboss.soa.esb.services.security.SecurityConfig;
+import org.jboss.soa.esb.services.security.SecurityConfigUtil;
 import org.jboss.soa.esb.services.security.SecurityContext;
 import org.jboss.soa.esb.services.security.SecurityService;
 import org.jboss.soa.esb.services.security.SecurityServiceException;
@@ -69,7 +74,7 @@
         jbossEsbProperties = System.getProperty(Environment.PROPERTIES_FILE);
         URL resource = ClassUtil.getResource("security-properties.xml", getClass());
         System.setProperty(Environment.PROPERTIES_FILE, "abs://" + resource.getFile());
-        
+
         URL loginConfig = ClassUtil.getResource("test_jaas.config", getClass());
         System.setProperty("java.security.auth.login.config", loginConfig.getFile());
     }
@@ -461,13 +466,15 @@
         Message message = MessageFactory.getInstance().getMessage();
 
         //  create an AuthenticationRequest which is needed to authenticate if the security
-        AuthenticationRequest build = new AuthenticationRequestImpl.Builder().build();
-        message.getContext().setContext(SecurityService.AUTH_REQUEST, PublicCryptoUtil.INSTANCE.encrypt((Serializable) build));
+        AuthenticationRequest authRequest = new AuthenticationRequestImpl.Builder().build();
+        byte[] encryptedAuthRequest = PublicCryptoUtil.INSTANCE.encrypt((Serializable) authRequest);
+        message.getContext().setContext(SecurityService.AUTH_REQUEST, encryptedAuthRequest);
 
         final boolean result = pipeline.process(message);
         assertTrue(result);
         assertEquals(new TestPrincipal("test").getName(), MockSecuredActionProcessor.getSubject().getPrincipals().iterator().next().getName());
 
+        assertEquals(encryptedAuthRequest, AuthenticationRequestImpl.getEncryptedAuthRequest());
         pipeline.destroy() ;
         checkOrder(MockActionInfo.getDestroyList()) ;
     }
@@ -528,11 +535,10 @@
 
         //  create and encrypt the security context. This simulates a call for a service
         //  that has already been authentcated..
-        SecurityContext securityContext = new SecurityContext(subject);
-        byte[] encrypt = SecurityContext.encryptContext(securityContext);
+        SecurityContext securityContext = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
+        SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+        message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
 
-        message.getContext().setContext(SecurityService.CONTEXT, encrypt);
-
         final boolean result = pipeline.process(message);
 
         assertTrue(result);
@@ -544,6 +550,89 @@
         checkOrder(MockActionInfo.getDestroyList()) ;
     }
 
+    public void testSecuredWithExistingSecurityContextExpired() throws Exception
+    {
+        final ConfigTree configTree = new ConfigTree("parent") ;
+        addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null);
+        configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+
+        addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+        final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+        pipeline.initialise() ;
+        checkOrder(MockActionInfo.getInitialiseList()) ;
+
+        Message message = MessageFactory.getInstance().getMessage();
+
+        Subject subject = new Subject();
+        //  add principal
+        User user = new User("AustinPowerwich");
+        subject.getPrincipals().add(user);
+        //  add public credentials
+        byte[] publicCred = "publicsecret".getBytes();
+        subject.getPublicCredentials().add(publicCred);
+        //  add private credentials
+        byte[] privateCred = "privatesecret".getBytes();
+        subject.getPrivateCredentials().add(privateCred);
+
+        //  create and encrypt the security context. This simulates a call for a service
+        //  that has already been authentcated...but with a very short timeout.
+        SecurityContext securityContext = new SecurityContext(subject, 10);
+
+        TimeUnit.SECONDS.sleep(1);
+
+        SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+        message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
+
+        boolean process = pipeline.process(message);
+        assertFalse(process);
+
+        pipeline.destroy() ;
+        checkOrder(MockActionInfo.getDestroyList()) ;
+    }
+
+    public void testSecuredWithSecurityContextOverriddenTimeout() throws Exception
+    {
+        final long timeout = 90000;
+
+        //  setup config tree
+        final ConfigTree configTree = new ConfigTree("parent") ;
+        final ConfigTree securityConfigTree = addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null, timeout);
+        configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+        addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+        final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+
+        final SecurityConfig securityConfig = SecurityConfigUtil.createSecurityConfig(securityConfigTree);
+
+        final long contextTimeout = pipeline.getSecurityContextTimeout(securityConfig);
+
+        assertEquals(timeout, contextTimeout);
+
+        pipeline.destroy() ;
+    }
+
+    public void testSecuredWithSecurityContextDefaultTimeout() throws Exception
+    {
+        final long timeout = 30000;
+
+        //  setup config tree
+        final ConfigTree configTree = new ConfigTree("parent") ;
+        final ConfigTree securityConfigTree = addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null);
+        configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+        addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+        final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+
+        final SecurityConfig securityConfig = SecurityConfigUtil.createSecurityConfig(securityConfigTree);
+
+        final long contextTimeout = pipeline.getSecurityContextTimeout(securityConfig);
+
+        assertEquals(timeout, contextTimeout);
+
+        pipeline.destroy() ;
+    }
+
     public void testSecuredWithSecurityContextRolesAllowedNegativeCheck() throws Exception
     {
         final ConfigTree configTree = new ConfigTree("parent") ;
@@ -565,11 +654,10 @@
         subject.getPublicCredentials().add(publicCred);
         byte[] privateCred = "privatesecret".getBytes();
         subject.getPrivateCredentials().add(privateCred);
-        SecurityContext securityContext = new SecurityContext(subject);
-        byte[] encrypt = SecurityContext.encryptContext(securityContext);
+        SecurityContext securityContext = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
+        SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+        message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
 
-        message.getContext().setContext(SecurityService.CONTEXT, encrypt);
-
         try
         {
             pipeline.process(message);
@@ -638,4 +726,22 @@
         return securityElement;
     }
 
+    private ConfigTree addSecurityConfig(
+            final ConfigTree parent,
+            final String runAs,
+            final String callerIdentity,
+            final String moduleName,
+            final String rolesAllowed,
+            final long timeout)
+    {
+        ConfigTree securityElement = this.addSecurityConfig(parent, runAs, callerIdentity, moduleName, rolesAllowed);
+        if (timeout != 0l)
+        {
+            ConfigTree property = new ConfigTree("property", securityElement);
+            property.setAttribute("name", Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+            property.setAttribute("value", Long.toString(timeout));
+        }
+        return securityElement;
+    }
+
 }

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml	2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,16 +41,17 @@
     	<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
     	<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
     	
-    	<property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+    	<property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+    	<property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
     	
+    	<property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+    	
     	<property name="org.jboss.soa.esb.services.security.publicKeystore" value="publicKeyStore"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyPassword" value="testPassword"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
+    	
     </properties>
     <properties name="registry">
     	<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -53,7 +53,7 @@
     @Test
     public void encryptAndDecrypt() throws SecurityServiceException, InvalidKeyException, NoSuchAlgorithmException, IOException, ClassNotFoundException
     {
-        String object = "some textaalddddddddddddddaldkfjlakjfafadlalkfdalfjkfladsjfalkfjfljsafkjalkfjjafjlkafjfjjfaadlasajfkafkjalalfkjakljdljfajfjajfljalkfjlafljalsjfjj";
+        final String object = getLongString(5000);
         byte[] encrypted = PublicCryptoUtil.INSTANCE.encrypt(object);
         assertFalse(object.equals(new String(encrypted)));
 
@@ -71,6 +71,16 @@
         }
     }
 
+    private String getLongString(final int size)
+    {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < size; i++)
+        {
+            sb.append(i);
+        }
+        return sb.toString();
+    }
+
     @Before
     public void setup() throws ConfigurationException
     {
@@ -79,6 +89,8 @@
         System.setProperty(Environment.PROPERTIES_FILE, "abs://" + resource.getFile());
     }
 
+
+
     @After
     public void tearDown()
     {

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,8 +20,8 @@
  */
 package org.jboss.soa.esb.services.security;
 
-import static org.junit.Assert.*;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -32,7 +32,9 @@
 import java.io.ObjectOutputStream;
 import java.net.URL;
 import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
 
+import javax.crypto.SealedObject;
 import javax.security.auth.Subject;
 
 import junit.framework.JUnit4TestAdapter;
@@ -53,7 +55,8 @@
 import org.junit.Test;
 
 /**
- *
+ * Unit test for SecurityContext.
+ * <p/>
  * @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
  *
  */
@@ -70,7 +73,7 @@
 		roles.addMember( new Role("Admin"));
 		subject.getPrincipals().add(roles);
 
-		SecurityContext securityContext = new SecurityContext(subject);
+		SecurityContext securityContext = new SecurityContext(subject, 30000);
 		boolean callerInRole = securityContext.isCallerInRole("Admin");
 		assertTrue( callerInRole );
 	}
@@ -84,7 +87,7 @@
         byte[] publicCred = "secret".getBytes();
         subject.getPublicCredentials().add(publicCred);
 
-        SecurityContext securityContext = new SecurityContext(subject);
+        SecurityContext securityContext = new SecurityContext(subject, 30000l);
         assertEquals( user, securityContext.getSubject().getPrincipals().iterator().next() );
         assertEquals( publicCred, securityContext.getSubject().getPublicCredentials().iterator().next());
 
@@ -102,7 +105,6 @@
         assertTrue (readObject instanceof SecurityContext);
         SecurityContext deserialized = (SecurityContext)readObject;
         assertEquals( user, deserialized.getSubject().getPrincipals().iterator().next() );
-        assertEquals( new String(publicCred), new String((byte[])deserialized.getPubCredentials().iterator().next()));
     }
 
 	@Test
@@ -114,12 +116,11 @@
         byte[] publicCred = "secret".getBytes();
         subject.getPublicCredentials().add(publicCred);
 
-        SecurityContext securityContext = new SecurityContext(subject);
+        SecurityContext securityContext = new SecurityContext(subject, 30000l);
         Message message = MessageFactory.getInstance().getMessage(MessageType.JAVA_SERIALIZED);
-        byte[] encryptContext = SecurityContext.encryptContext(securityContext);
-        message.getContext().setContext(SecurityService.CONTEXT, encryptContext);
+        SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+        message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
 
-
         //  serialize object
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
         ObjectOutputStream out = new ObjectOutputStream(bout);
@@ -133,10 +134,8 @@
         //  assert that the content is still matches.
         assertTrue (readObject instanceof Message);
         Message deserializedMsg = (Message) readObject;
-        SecurityContext deserialized = SecurityContext.decryptContext((byte[]) deserializedMsg.getContext().getContext(SecurityService.CONTEXT));
+        SecurityContext deserialized = SecurityContext.decryptContext((SealedObject) deserializedMsg.getContext().getContext(SecurityService.CONTEXT));
         assertEquals( user, deserialized.getSubject().getPrincipals().iterator().next() );
-        //assertEquals( new String(publicCred), new String((byte[])deserialized.getPubCredentials().iterator().next()));
-        assertEquals( new String(publicCred), new String((byte[])deserialized.getSubject().getPublicCredentials().iterator().next()));
     }
 
 	@Test
@@ -150,13 +149,12 @@
         byte[] privateCred = "privatesecret".getBytes();
         subject.getPrivateCredentials().add(privateCred);
 
-        SecurityContext securityContext = new SecurityContext(subject);
-        byte[] encrypt = SecurityContext.encryptContext(securityContext);
-        assertNotNull(encrypt);
+        SecurityContext securityContext = new SecurityContext(subject, 30000);
+        SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+        assertNotNull(sealedObject);
 
-        SecurityContext decryptContext = SecurityContext.decryptContext(encrypt);
-        assertEquals( new String(publicCred), new String((byte[])decryptContext.getPubCredentials().iterator().next()));
-        assertEquals( new String(privateCred), new String((byte[])decryptContext.getPrivCredentials().iterator().next()));
+        SecurityContext decryptContext = SecurityContext.decryptContext(sealedObject);
+        assertEquals( user, decryptContext.getSubject().getPrincipals().iterator().next());
 	}
 
 	@Test
@@ -170,7 +168,7 @@
         byte[] privateCred = "privatesecret".getBytes();
         subject.getPrivateCredentials().add(privateCred);
 
-        SecurityContext securityContext = new SecurityContext(subject);
+        SecurityContext securityContext = new SecurityContext(subject, 30000);
 
         HashSet<Object> credentials = new HashSet<Object>();
         credentials.add(publicCred);
@@ -186,6 +184,41 @@
         assertFalse(securityContext.compareTo(null));
     }
 
+	@Test
+	public void timeout() throws InterruptedException
+	{
+        final Subject subject = new Subject();
+        SecurityContext context = new SecurityContext(subject, 30000);
+        assertTrue("Default is 5 min so context should be valid", context.isValid());
+
+        context = new SecurityContext(subject, 100);
+        TimeUnit.SECONDS.sleep(1);
+        assertFalse(context.isValid());
+
+        context = new SecurityContext(subject, 1000);
+        assertTrue(context.isValid());
+	}
+
+	@Test
+    public void constructWithNeverExpiringContext()
+    {
+        SecurityContext securityContext = new SecurityContext(new Subject(), -1);
+        assertTrue(securityContext.isValid());
+    }
+
+	@Test (expected = IllegalArgumentException.class )
+    public void shouldThrowIfTimeoutIsNegative()
+    {
+        new SecurityContext(new Subject(), -2);
+    }
+
+	@Test
+    public void getConfigurationTimeout() throws SecurityServiceException
+    {
+        final long timeout = SecurityContext.getConfigurationTimeout();
+        assertEquals("timeout should match the value in security-properties.xml", 30000l, timeout);
+    }
+
 	@Before
     public void setup() throws ConfigurationException
     {

Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml	2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml	2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,16 +41,17 @@
     	<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
     	<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
     	
-    	<property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
-    	<property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+    	<property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+    	<property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
     	
+    	<property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+    	
     	<property name="org.jboss.soa.esb.services.security.publicKeystore" value="publicKeyStore"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyPassword" value="testPassword"/>
     	<property name="org.jboss.soa.esb.services.security.publicKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
+    	
     </properties>
     <properties name="registry">
     	<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>

Added: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java	                        (rev 0)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java	2008-10-20 09:08:16 UTC (rev 23518)
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source Copyright 2008, Red Hat Middleware
+ * LLC, and individual contributors by the @authors tag. See the copyright.txt
+ * in the distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
+package org.jboss.soa.esb.services.security.util;
+
+import static org.junit.Assert.*;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.jboss.soa.esb.services.security.SecurityServiceException;
+import org.junit.Test;
+
+import junit.framework.JUnit4TestAdapter;
+
+/**
+ * Unit test from CryptoUtil.
+ *
+ * @author <a href="mailto:dbevenius at jboss.com">Daniel Bevenius</a>
+ *
+ */
+public class CryptoUtilUnitTest
+{
+    @Test
+    public void encryptDecryptRSA() throws NoSuchAlgorithmException, SecurityServiceException
+    {
+        final String payload = "Some text...";
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(1024);
+        KeyPair keyPair = keyGen.generateKeyPair();
+
+        byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , keyPair.getPublic(), keyPair.getPublic().getAlgorithm());
+        byte[] decrypt = CryptoUtil.decrypt(encrypt, keyPair.getPrivate(), keyPair.getPrivate().getAlgorithm());
+        assertEquals(payload, new String(decrypt));
+    }
+
+    @Test
+    public void encryptDecryptDES() throws NoSuchAlgorithmException, SecurityServiceException
+    {
+        final String payload = "Some text...";
+        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+        keyGen.init(56);
+        SecretKey secretKey = keyGen.generateKey();
+        final String transformation = "DES/ECB/PKCS5Padding";
+
+        byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+        byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+        assertEquals(payload, new String(decrypt));
+    }
+
+    @Test
+    public void encryptDecryptTripleDES() throws NoSuchAlgorithmException, SecurityServiceException
+    {
+        dumpSecurityProviders();
+        final String payload = "Some text...";
+        KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
+        keyGen.init(128);
+        SecretKey secretKey = keyGen.generateKey();
+        final String transformation = "Blowfish/ECB/PKCS5Padding";
+
+        byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+        byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+        assertEquals(payload, new String(decrypt));
+    }
+
+    @Test
+    public void encryptDecryptTripleEAS() throws NoSuchAlgorithmException, SecurityServiceException
+    {
+        final String payload = "Some text...";
+        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
+        keyGen.init(128);
+        SecretKey secretKey = keyGen.generateKey();
+        final String transformation = "AES/ECB/PKCS5Padding";
+
+        byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+        byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+        assertEquals(payload, new String(decrypt));
+    }
+
+
+    @SuppressWarnings("unused")
+    private void dumpSecurityProviders()
+    {
+        Provider[]  providers = Security.getProviders();
+        for (Provider provider : providers)
+        {
+            System.out.println(provider.getServices());
+        }
+    }
+
+    public static junit.framework.Test suite()
+    {
+        return new JUnit4TestAdapter(CryptoUtilUnitTest.class);
+    }
+
+}




More information about the jboss-svn-commits mailing list