knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lmc...@apache.org
Subject knox git commit: KNOX-1230 - Many Concurrent Requests to Knox causes URL Mangling
Date Fri, 30 Mar 2018 15:27:26 GMT
Repository: knox
Updated Branches:
  refs/heads/master c7f28551f -> fe84b0456


KNOX-1230 - Many Concurrent Requests to Knox causes URL Mangling

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/fe84b045
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/fe84b045
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/fe84b045

Branch: refs/heads/master
Commit: fe84b04561f6131ddc0593fb811cd1bfba21316d
Parents: c7f2855
Author: Larry McCay <lmccay@hortonworks.com>
Authored: Fri Mar 30 11:26:57 2018 -0400
Committer: Larry McCay <lmccay@hortonworks.com>
Committed: Fri Mar 30 11:26:57 2018 -0400

----------------------------------------------------------------------
 .../SecureQueryDecryptProcessor.java            |  30 +-
 .../SecureQueryEncryptProcessor.java            |  21 +-
 .../securequery/SecureQueryMessages.java        |   5 +
 .../security/impl/DefaultCryptoService.java     |  20 +-
 .../security/impl/DefaultKeystoreService.java   | 399 +++++++++++++------
 .../dispatch/AbstractGatewayDispatch.java       |   4 +-
 .../knox/gateway/dispatch/DefaultDispatch.java  |   2 +-
 .../gateway/dispatch/GatewayDispatchFilter.java |  56 +--
 .../security/impl/CMFMasterService.java         |   4 +-
 .../security/impl/ConfigurableEncryptor.java    |  91 +----
 10 files changed, 376 insertions(+), 256 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
index 3cccc4d..77e990e 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryDecryptProcessor.java
@@ -18,13 +18,14 @@
 package org.apache.knox.gateway.securequery;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
-import org.apache.knox.gateway.services.GatewayServices;
-import org.apache.knox.gateway.services.security.CryptoService;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.services.security.EncryptionResult;
+import org.apache.knox.gateway.services.security.impl.ConfigurableEncryptor;
 import org.apache.knox.gateway.util.urltemplate.Builder;
 import org.apache.knox.gateway.util.urltemplate.Query;
 import org.apache.knox.gateway.util.urltemplate.Template;
@@ -36,10 +37,10 @@ import java.util.StringTokenizer;
 public class SecureQueryDecryptProcessor implements
     UrlRewriteStepProcessor<SecureQueryDecryptDescriptor> {
 
+  private static SecureQueryMessages log = MessagesFactory.get( SecureQueryMessages.class
);
   private static final String ENCRYPTED_PARAMETER_NAME = "_";
 
-  private String clusterName;
-  private CryptoService cryptoService;
+  private ConfigurableEncryptor encryptor = null;
 
   @Override
   public String getType() {
@@ -48,9 +49,8 @@ public class SecureQueryDecryptProcessor implements
 
   @Override
   public void initialize( UrlRewriteEnvironment environment, SecureQueryDecryptDescriptor
descriptor ) throws Exception {
-    clusterName = environment.getAttribute( GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE );
-    GatewayServices services = environment.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+    encryptor = new ConfigurableEncryptor("encryptQueryString");
+    encryptor.init((GatewayConfig)environment.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE));
   }
 
   @Override
@@ -107,13 +107,17 @@ public class SecureQueryDecryptProcessor implements
   String decode( String string ) throws UnsupportedEncodingException {
     byte[] bytes = Base64.decodeBase64( string );
     EncryptionResult result = EncryptionResult.fromByteArray(bytes);
-    byte[] clear = cryptoService.decryptForCluster(clusterName, 
-        "encryptQueryString", 
-        result.cipher, 
-        result.iv, 
-        result.salt);
+    byte[] clear = null;
+    try {
+      clear = encryptor.decrypt(
+          result.salt, 
+          result.iv, 
+          result.cipher);
+    } catch (Exception e) {
+      log.unableToDecryptValue(e);
+    }
     if (clear != null) {
-      return new String(clear);
+      return new String(clear, "UTF-8");
     }
     return null;
   }

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
index 5e44d20..f24b539 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryEncryptProcessor.java
@@ -18,13 +18,14 @@
 package org.apache.knox.gateway.securequery;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
 import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
-import org.apache.knox.gateway.services.GatewayServices;
-import org.apache.knox.gateway.services.security.CryptoService;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.services.security.EncryptionResult;
+import org.apache.knox.gateway.services.security.impl.ConfigurableEncryptor;
 import org.apache.knox.gateway.util.urltemplate.Parser;
 import org.apache.knox.gateway.util.urltemplate.Template;
 
@@ -33,10 +34,10 @@ import java.io.UnsupportedEncodingException;
 public class SecureQueryEncryptProcessor
     implements UrlRewriteStepProcessor<SecureQueryEncryptDescriptor> {
 
+  private static SecureQueryMessages log = MessagesFactory.get( SecureQueryMessages.class
);
   private static final String ENCRYPTED_PARAMETER_NAME = "_";
 
-  private String clusterName;
-  private CryptoService cryptoService = null;
+  private ConfigurableEncryptor encryptor;
 
   @Override
   public String getType() {
@@ -45,9 +46,8 @@ public class SecureQueryEncryptProcessor
 
   @Override
   public void initialize( UrlRewriteEnvironment environment, SecureQueryEncryptDescriptor
descriptor ) throws Exception {
-    clusterName = environment.getAttribute( GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE );
-    GatewayServices services = environment.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+    encryptor = new ConfigurableEncryptor("encryptQueryString");
+    encryptor.init((GatewayConfig)environment.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE));
   }
 
   @Override
@@ -77,7 +77,12 @@ public class SecureQueryEncryptProcessor
   }
 
   private String encode( String string ) throws UnsupportedEncodingException {
-    EncryptionResult result = cryptoService.encryptForCluster(clusterName, "encryptQueryString",
string.getBytes("UTF-8"));
+    EncryptionResult result = null;
+    try {
+      result = encryptor.encrypt(string);
+    } catch (Exception e) {
+      log.unableToEncryptValue(e);
+    }
     string = Base64.encodeBase64URLSafeString(result.toByteAray());
     return string;
   }

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
index 2375011..c7990f2 100644
--- a/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
+++ b/gateway-provider-rewrite-step-secure-query/src/main/java/org/apache/knox/gateway/securequery/SecureQueryMessages.java
@@ -28,4 +28,9 @@ public interface SecureQueryMessages {
   @Message( level = MessageLevel.ERROR, text = "Failed to create or verify the presence of
a password for query string encryption: {0}" )
   void unableCreatePasswordForEncryption(@StackTrace( level = MessageLevel.DEBUG ) Exception
e);
 
+  @Message( level = MessageLevel.ERROR, text = "Failed to encrypt a sensitive value due to
an exception: {0}" )
+  void unableToEncryptValue(@StackTrace( level = MessageLevel.ERROR ) Exception e);
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to decrypt a sensitive value due to
an exception: {0}" )
+  void unableToDecryptValue(@StackTrace( level = MessageLevel.ERROR ) Exception e);
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
index f47a17b..584255e 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultCryptoService.java
@@ -122,13 +122,16 @@ public class DefaultCryptoService implements CryptoService {
   @Override
   public byte[] decryptForCluster(String clusterName, String alias, byte[] cipherText, byte[]
iv, byte[] salt) {
     try {
-      final char[] password = as.getPasswordFromAliasForCluster(clusterName, alias);
-      if (password != null) {
-        try {
-          return getEncryptor(clusterName,password ).decrypt( salt, iv, cipherText);
-        } catch (Exception e) {
-          LOG.failedToDecryptPasswordForCluster( clusterName, e );
-        }
+      char[] password = null;
+      ConfigurableEncryptor encryptor = null;
+        password = as.getPasswordFromAliasForCluster(clusterName, alias);
+        if (password != null) {
+          encryptor = getEncryptor(clusterName,password );
+          try {
+            return encryptor.decrypt( salt, iv, cipherText);
+          } catch (Exception e) {
+            LOG.failedToDecryptPasswordForCluster( clusterName, e );
+          }
       }
       else {
         LOG.failedToDecryptCipherForClusterNullPassword( clusterName );
@@ -167,7 +170,8 @@ public class DefaultCryptoService implements CryptoService {
   @Override
   public byte[] sign(String algorithm, String alias, String payloadToSign) {
     try {
-      char[] passphrase = as.getGatewayIdentityPassphrase();
+      char[] passphrase = null;
+      passphrase = as.getGatewayIdentityPassphrase();
       PrivateKey privateKey = (PrivateKey) ks.getKeyForGateway(alias, passphrase);
       Signature signature = Signature.getInstance(algorithm);
       signature.initSign(privateKey);

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
index 5d4bd27..f4cf523 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/services/security/impl/DefaultKeystoreService.java
@@ -29,6 +29,7 @@ import org.apache.knox.gateway.services.security.KeystoreServiceException;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.security.GeneralSecurityException;
 import java.security.Key;
@@ -41,7 +42,12 @@ import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.text.MessageFormat;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 public class DefaultKeystoreService extends BaseKeystoreService implements
     KeystoreService, Service {
@@ -57,10 +63,17 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
 
   private String signingKeystoreName = null;
   private String signingKeyAlias = null;
+  private Map<String, Map<String, String>> cache = new ConcurrentHashMap<String,Map<String,
String>>();
+  private Lock readLock = null;
+  private Lock writeLock = null;
 
   @Override
   public void init(GatewayConfig config, Map<String, String> options)
       throws ServiceLifecycleException {
+    ReadWriteLock lock = new ReentrantReadWriteLock(true);
+    readLock = lock.readLock();
+    writeLock = lock.writeLock();
+
     this.keyStoreDir = config.getGatewaySecurityDir() + File.separator + "keystores" + File.separator;
     File ksd = new File(this.keyStoreDir);
     if (!ksd.exists()) {
@@ -106,20 +119,31 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
 
   @Override
   public void createKeystoreForGateway() throws KeystoreServiceException {
-    String filename = getKeystorePath();
-    createKeystore(filename, "JKS");
+    writeLock.lock();
+    try {
+      String filename = getKeystorePath();
+      createKeystore(filename, "JKS");
+    } 
+    finally {
+      writeLock.unlock();
+    }
   }
 
   @Override
   public KeyStore getKeystoreForGateway() throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
-    return getKeystore(keyStoreFile, "JKS");
+    readLock.lock();
+    try {
+      return getKeystore(keyStoreFile, "JKS");
+    }
+    finally {
+      readLock.unlock();
+    }
   }
 
   @Override
   public KeyStore getSigningKeystore() throws KeystoreServiceException {
     File  keyStoreFile = null;
-
     if (signingKeystoreName == null) {
       keyStoreFile = new File(keyStoreDir + GATEWAY_KEYSTORE);
     }
@@ -130,53 +154,70 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
         throw new KeystoreServiceException("Configured signing keystore does not exist.");
       }
     }
-    return getKeystore(keyStoreFile, "JKS");
+    readLock.lock();
+    try {
+      return getKeystore(keyStoreFile, "JKS");
+    }
+    finally {
+      readLock.unlock();
+    }
   }
 
   @Override
   public void addSelfSignedCertForGateway(String alias, char[] passphrase) throws KeystoreServiceException
{
-    addSelfSignedCertForGateway(alias, passphrase, null);
+    writeLock.lock();
+    try {
+      addSelfSignedCertForGateway(alias, passphrase, null);
+    }
+    finally {
+        writeLock.unlock();
+    }
   }
 
   @Override
   public void addSelfSignedCertForGateway(String alias, char[] passphrase, String hostname)

       throws KeystoreServiceException {
-
-    KeyPairGenerator keyPairGenerator;
+    writeLock.lock();
     try {
-      keyPairGenerator = KeyPairGenerator.getInstance("RSA");
-      keyPairGenerator.initialize(1024);  
-      KeyPair KPair = keyPairGenerator.generateKeyPair();
-      if (hostname == null) {
-        hostname = System.getProperty(CERT_GEN_MODE, CERT_GEN_MODE_LOCALHOST);
-      }
-      X509Certificate cert = null;
-      if(hostname.equals(CERT_GEN_MODE_HOSTNAME)) {
-        String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
-        cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
-      }
-      else {
-        String dn = buildDistinguishedName(hostname);
-        cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+      KeyPairGenerator keyPairGenerator;
+      try {
+        keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(1024);  
+        KeyPair KPair = keyPairGenerator.generateKeyPair();
+        if (hostname == null) {
+          hostname = System.getProperty(CERT_GEN_MODE, CERT_GEN_MODE_LOCALHOST);
+        }
+        X509Certificate cert = null;
+        if(hostname.equals(CERT_GEN_MODE_HOSTNAME)) {
+          String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
+          cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+        }
+        else {
+          String dn = buildDistinguishedName(hostname);
+          cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+        }
+  
+        KeyStore privateKS = getKeystoreForGateway();
+        privateKS.setKeyEntry(alias, KPair.getPrivate(),  
+            passphrase,  
+            new java.security.cert.Certificate[]{cert});  
+        
+        writeKeystoreToFile(privateKS, new File( keyStoreDir + GATEWAY_KEYSTORE  ));
+        //writeCertificateToFile( cert, new File( keyStoreDir + alias + ".pem" ) );
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToAddSeflSignedCertForGateway( alias, e );
+        throw new KeystoreServiceException(e);
+      } catch (GeneralSecurityException e) {
+        LOG.failedToAddSeflSignedCertForGateway( alias, e );
+        throw new KeystoreServiceException(e);
+      } catch (IOException e) {
+        LOG.failedToAddSeflSignedCertForGateway( alias, e );
+        throw new KeystoreServiceException(e);
       }
-
-      KeyStore privateKS = getKeystoreForGateway();
-      privateKS.setKeyEntry(alias, KPair.getPrivate(),  
-          passphrase,  
-          new java.security.cert.Certificate[]{cert});  
-      
-      writeKeystoreToFile(privateKS, new File( keyStoreDir + GATEWAY_KEYSTORE  ));
-      //writeCertificateToFile( cert, new File( keyStoreDir + alias + ".pem" ) );
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToAddSeflSignedCertForGateway( alias, e );
-      throw new KeystoreServiceException(e);
-    } catch (GeneralSecurityException e) {
-      LOG.failedToAddSeflSignedCertForGateway( alias, e );
-      throw new KeystoreServiceException(e);
-    } catch (IOException e) {
-      LOG.failedToAddSeflSignedCertForGateway( alias, e );
-      throw new KeystoreServiceException(e);
-    }  
+    }
+    finally {
+      writeLock.unlock();
+    }
   }
 
   private String buildDistinguishedName(String hostname) {
@@ -190,147 +231,255 @@ public class DefaultKeystoreService extends BaseKeystoreService implements
   @Override
   public void createCredentialStoreForCluster(String clusterName) throws KeystoreServiceException
{
     String filename = keyStoreDir + clusterName + CREDENTIALS_SUFFIX;
-    createKeystore(filename, "JCEKS");
+    writeLock.lock();
+    try {
+      createKeystore(filename, "JCEKS");
+    }
+    finally {
+      writeLock.unlock();
+    }
   }
 
   @Override
   public boolean isCredentialStoreForClusterAvailable(String clusterName) throws KeystoreServiceException
{
     boolean rc = false;
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX 
);
+    readLock.lock();
     try {
-      rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
-    } catch (KeyStoreException e) {
-      throw new KeystoreServiceException(e);
-    } catch (IOException e) {
-      throw new KeystoreServiceException(e);
+      try {
+        rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
+      } catch (KeyStoreException e) {
+        throw new KeystoreServiceException(e);
+      } catch (IOException e) {
+        throw new KeystoreServiceException(e);
+      }
+      return rc;
+    }
+    finally {
+      readLock.unlock();
     }
-    return rc;
   }
 
   @Override
   public boolean isKeystoreForGatewayAvailable() throws KeystoreServiceException {
     boolean rc = false;
     final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
+    readLock.lock();
     try {
-      rc = isKeystoreAvailable(keyStoreFile, "JKS");
-    } catch (KeyStoreException e) {
-      throw new KeystoreServiceException(e);
-    } catch (IOException e) {
-      throw new KeystoreServiceException(e);
+      try {
+        rc = isKeystoreAvailable(keyStoreFile, "JKS");
+      } catch (KeyStoreException e) {
+        throw new KeystoreServiceException(e);
+      } catch (IOException e) {
+        throw new KeystoreServiceException(e);
+      }
+      return rc;
+    }
+    finally {
+      readLock.unlock();
     }
-    return rc;
   }
 
   @Override
   public Key getKeyForGateway(String alias, char[] passphrase) throws KeystoreServiceException
{
     Key key = null;
-    KeyStore ks = getKeystoreForGateway();
-    if (passphrase == null) {
-      passphrase = masterService.getMasterSecret();
-      LOG.assumingKeyPassphraseIsMaster();
-    }
-    if (ks != null) {
-      try {
-        key = ks.getKey(alias, passphrase);
-      } catch (UnrecoverableKeyException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
-      } catch (KeyStoreException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
+    readLock.lock();
+    try {
+      KeyStore ks = getKeystoreForGateway();
+      if (passphrase == null) {
+        passphrase = masterService.getMasterSecret();
+        LOG.assumingKeyPassphraseIsMaster();
+      }
+      if (ks != null) {
+        try {
+          key = ks.getKey(alias, passphrase);
+        } catch (UnrecoverableKeyException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        } catch (KeyStoreException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        } catch (NoSuchAlgorithmException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        }
       }
+      return key;
+    }
+    finally {
+      readLock.unlock();
     }
-    return key;
   }  
 
   @Override
   public Key getSigningKey(String alias, char[] passphrase) throws KeystoreServiceException
{
     Key key = null;
-    KeyStore ks = getSigningKeystore();
-    if (passphrase == null) {
-      passphrase = masterService.getMasterSecret();
-      LOG.assumingKeyPassphraseIsMaster();
-    }
-    if (ks != null) {
-      try {
-        key = ks.getKey(alias, passphrase);
-      } catch (UnrecoverableKeyException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
-      } catch (KeyStoreException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToGetKeyForGateway( alias, e );
+    readLock.lock();
+    try {
+      KeyStore ks = getSigningKeystore();
+      if (passphrase == null) {
+        passphrase = masterService.getMasterSecret();
+        LOG.assumingKeyPassphraseIsMaster();
       }
+      if (ks != null) {
+        try {
+          key = ks.getKey(alias, passphrase);
+        } catch (UnrecoverableKeyException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        } catch (KeyStoreException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        } catch (NoSuchAlgorithmException e) {
+          LOG.failedToGetKeyForGateway( alias, e );
+        }
+      }
+      return key;
+    }
+    finally {
+      readLock.unlock();
     }
-    return key;
   }
 
   public KeyStore getCredentialStoreForCluster(String clusterName) 
       throws KeystoreServiceException {
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX 
);
-    return getKeystore(keyStoreFile, "JCEKS");
+    readLock.lock();
+    try {
+      return getKeystore(keyStoreFile, "JCEKS");
+    }
+    finally {
+      readLock.unlock();
+    }
   }
 
   public void addCredentialForCluster(String clusterName, String alias, String value) 
       throws KeystoreServiceException {
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    addCredential(alias, value, ks);
-    final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX 
);
+    writeLock.lock();
     try {
-      writeKeystoreToFile(ks, keyStoreFile);
-    } catch (KeyStoreException e) {
-      LOG.failedToAddCredentialForCluster( clusterName, e );
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToAddCredentialForCluster( clusterName, e );
-    } catch (CertificateException e) {
-      LOG.failedToAddCredentialForCluster( clusterName, e );
-    } catch (IOException e) {
-      LOG.failedToAddCredentialForCluster( clusterName, e );
+      removeFromCache(clusterName, alias);
+      KeyStore ks = getCredentialStoreForCluster(clusterName);
+      addCredential(alias, value, ks);
+      final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX
 );
+      try {
+        writeKeystoreToFile(ks, keyStoreFile);
+      } catch (KeyStoreException e) {
+        LOG.failedToAddCredentialForCluster( clusterName, e );
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToAddCredentialForCluster( clusterName, e );
+      } catch (CertificateException e) {
+        LOG.failedToAddCredentialForCluster( clusterName, e );
+      } catch (IOException e) {
+        LOG.failedToAddCredentialForCluster( clusterName, e );
+      }
+    } finally {
+      writeLock.unlock();
     }
   }
-  
+
   @Override
   public char[] getCredentialForCluster(String clusterName, String alias) 
       throws KeystoreServiceException {
     char[] credential = null;
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    if (ks != null) {
-      try {
-        char[] masterSecret = masterService.getMasterSecret();
-        Key credentialKey = ks.getKey( alias, masterSecret );
-        if (credentialKey != null) {
-          byte[] credentialBytes = credentialKey.getEncoded();
-          String credentialString = new String( credentialBytes );
-          credential = credentialString.toCharArray();
+    readLock.lock();
+    try {
+      credential = checkCache(clusterName, alias);
+      if (credential == null) {
+        KeyStore ks = getCredentialStoreForCluster(clusterName);
+        if (ks != null) {
+          try {
+            char[] masterSecret = masterService.getMasterSecret();
+            Key credentialKey = ks.getKey( alias, masterSecret );
+            if (credentialKey != null) {
+              byte[] credentialBytes = credentialKey.getEncoded();
+              String credentialString = new String( credentialBytes, "UTF-8" );
+              credential = credentialString.toCharArray();
+              addToCache(clusterName, alias, credentialString);
+            }
+          } catch (UnrecoverableKeyException e) {
+            LOG.failedToGetCredentialForCluster( clusterName, e );
+          } catch (KeyStoreException e) {
+            LOG.failedToGetCredentialForCluster( clusterName, e );
+          } catch (NoSuchAlgorithmException e) {
+            LOG.failedToGetCredentialForCluster( clusterName, e );
+          } catch (UnsupportedEncodingException e) {
+            LOG.failedToGetCredentialForCluster( clusterName, e );
+           }
+  
         }
-      } catch (UnrecoverableKeyException e) {
-        LOG.failedToGetCredentialForCluster( clusterName, e );
-      } catch (KeyStoreException e) {
-        LOG.failedToGetCredentialForCluster( clusterName, e );
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToGetCredentialForCluster( clusterName, e );
       }
+      return credential;
+    }
+    finally {
+      readLock.unlock();
     }
-    return credential;
   }
 
-
   @Override
   public void removeCredentialForCluster(String clusterName, String alias) throws KeystoreServiceException
{
-    KeyStore ks = getCredentialStoreForCluster(clusterName);
-    removeCredential(alias, ks);
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX 
);
+    writeLock.lock();
     try {
-      writeKeystoreToFile(ks, keyStoreFile);
-    } catch (KeyStoreException e) {
-      LOG.failedToRemoveCredentialForCluster(clusterName, e);
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToRemoveCredentialForCluster(clusterName, e);
-    } catch (CertificateException e) {
-      LOG.failedToRemoveCredentialForCluster(clusterName, e);
-    } catch (IOException e) {
-      LOG.failedToRemoveCredentialForCluster(clusterName, e);
+      removeFromCache(clusterName, alias);
+      KeyStore ks = getCredentialStoreForCluster(clusterName);
+      removeCredential(alias, ks);
+      try {
+        writeKeystoreToFile(ks, keyStoreFile);
+      } catch (KeyStoreException e) {
+        LOG.failedToRemoveCredentialForCluster(clusterName, e);
+      } catch (NoSuchAlgorithmException e) {
+        LOG.failedToRemoveCredentialForCluster(clusterName, e);
+      } catch (CertificateException e) {
+        LOG.failedToRemoveCredentialForCluster(clusterName, e);
+      } catch (IOException e) {
+        LOG.failedToRemoveCredentialForCluster(clusterName, e);
+      }
     }
+    finally {
+      writeLock.unlock();
+    }
+  }
+
+  /**
+   * Called only from within critical sections of other methods above.
+   * @param clusterName
+   * @param alias
+   * @return
+   */
+  private char[] checkCache(String clusterName, String alias) {
+    char[] c = null;
+    String cred = null;
+      HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+      if (clusterCache == null) {
+        return null;
+      }
+      cred = clusterCache.get(alias);
+      if (cred != null) {
+        c = cred.toCharArray();
+      }
+      return c;
+  }
+
+  /**
+   * Called only from within critical sections of other methods above.
+   * @param clusterName
+   * @param alias
+   * @param credentialString
+   */
+  private void addToCache(String clusterName, String alias, String credentialString) {
+      HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+      if (clusterCache == null) {
+        clusterCache = new HashMap<String, String>();
+      }
+      clusterCache.put(alias, credentialString);
+  }
+
+  /**
+   * Called only from within critical sections of other methods above.
+   * @param clusterName
+   * @param alias
+   */
+  private void removeFromCache(String clusterName, String alias) {
+      HashMap<String, String> clusterCache = (HashMap<String, String>) cache.get(clusterName);
+      if (clusterCache == null) {
+        return;
+      }
+      clusterCache.remove(alias);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
index 0377142..d89a1dd 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/AbstractGatewayDispatch.java
@@ -70,12 +70,12 @@ public abstract class AbstractGatewayDispatch implements Dispatch {
   }
 
   @Override
-  public HttpClient getHttpClient() {
+  synchronized public HttpClient getHttpClient() {
     return client;
   }
 
   @Override
-  public void setHttpClient(HttpClient client) {
+  synchronized public void setHttpClient(HttpClient client) {
     this.client = client;
   }
 

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
index c2c1b53..4f8c82f 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
@@ -127,7 +127,7 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
         // Hadoop cluster not Kerberos enabled
         addCredentialsToRequest( outboundRequest );
       }
-      inboundResponse = client.execute( outboundRequest );
+      inboundResponse = getHttpClient().execute( outboundRequest );
 
       int statusCode = inboundResponse.getStatusLine().getStatusCode();
       if( statusCode != 201 ) {

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
index 8bef80d..8f3399a 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/GatewayDispatchFilter.java
@@ -41,6 +41,8 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
 
   protected static final SpiGatewayMessages LOG = MessagesFactory.get(SpiGatewayMessages.class);
 
+  private final Object lock = new Object();
+
   private Dispatch dispatch;
 
   private HttpClient httpClient;
@@ -59,41 +61,49 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
   @Override
   public void init(FilterConfig filterConfig) throws ServletException {
     super.init(filterConfig);
-    if (dispatch == null) {
-      String dispatchImpl = filterConfig.getInitParameter("dispatch-impl");
-      dispatch = newInstanceFromName(dispatchImpl);
-    }
-    ConfigurationInjectorBuilder.configuration().target(dispatch).source(filterConfig).inject();
-    HttpClientFactory httpClientFactory;
-    String httpClientFactoryClass = filterConfig.getInitParameter("httpClientFactory");
-    if (httpClientFactoryClass != null) {
-      httpClientFactory = newInstanceFromName(httpClientFactoryClass);
-    } else {
-      httpClientFactory = new DefaultHttpClientFactory();
+    synchronized(lock) {
+      if (dispatch == null) {
+        String dispatchImpl = filterConfig.getInitParameter("dispatch-impl");
+        dispatch = newInstanceFromName(dispatchImpl);
+      }
+      ConfigurationInjectorBuilder.configuration().target(dispatch).source(filterConfig).inject();
+      HttpClientFactory httpClientFactory;
+      String httpClientFactoryClass = filterConfig.getInitParameter("httpClientFactory");
+      if (httpClientFactoryClass != null) {
+        httpClientFactory = newInstanceFromName(httpClientFactoryClass);
+      } else {
+        httpClientFactory = new DefaultHttpClientFactory();
+      }
+      httpClient = httpClientFactory.createHttpClient(filterConfig);
+      dispatch.setHttpClient(httpClient);
+      dispatch.init();
     }
-    httpClient = httpClientFactory.createHttpClient(filterConfig);
-    dispatch.setHttpClient(httpClient);
-    dispatch.init();
   }
 
   @Override
   public void destroy() {
-    dispatch.destroy();
-    try {
-      if (httpClient instanceof  CloseableHttpClient) {
-        ((CloseableHttpClient) httpClient).close();
+    synchronized(lock) {
+      dispatch.destroy();
+      try {
+        if (httpClient instanceof  CloseableHttpClient) {
+          ((CloseableHttpClient) httpClient).close();
+        }
+      } catch ( IOException e ) {
+        LOG.errorClosingHttpClient(e);
       }
-    } catch ( IOException e ) {
-      LOG.errorClosingHttpClient(e);
     }
   }
 
   public Dispatch getDispatch() {
-    return dispatch;
+    synchronized(lock) {
+      return dispatch;
+    }
   }
 
   public void setDispatch(Dispatch dispatch) {
-    this.dispatch = dispatch;
+    synchronized(lock) {
+      this.dispatch = dispatch;
+    }
   }
 
   @Override
@@ -102,7 +112,7 @@ public class GatewayDispatchFilter extends AbstractGatewayFilter {
     Adapter adapter = METHOD_ADAPTERS.get(method);
     if ( adapter != null ) {
       try {
-        adapter.doMethod(dispatch, request, response);
+        adapter.doMethod(getDispatch(), request, response);
       } catch ( URISyntaxException e ) {
         throw new ServletException(e);
       }

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
index 15919f8..b39e6ab 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/CMFMasterService.java
@@ -167,7 +167,9 @@ public class CMFMasterService {
         LOG.loadingFromPersistentMaster( tag );
         String line = new String(Base64.decodeBase64(lines.get(1)));
         String[] parts = line.split("::");
-        this.master = new String(encryptor.decrypt(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]),
Base64.decodeBase64(parts[2])), "UTF8").toCharArray();
+        this.master = new String(encryptor.decrypt(Base64.decodeBase64(parts[0]),
+            Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2])),
+            "UTF8").toCharArray();
       } catch (IOException e) {
         LOG.failedToInitializeFromPersistentMaster(masterFile.getName(), e);
         throw e;

http://git-wip-us.apache.org/repos/asf/knox/blob/fe84b045/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
index b576f29..ed7feac 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/impl/ConfigurableEncryptor.java
@@ -17,16 +17,12 @@
  */
 package org.apache.knox.gateway.services.security.impl;
 
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
 import java.security.spec.KeySpec;
 
 import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.IvParameterSpec;
@@ -44,10 +40,6 @@ public class ConfigurableEncryptor {
   private static final int ITERATION_COUNT = 65536;
   private static final int KEY_LENGTH = 128;
   
-  private Cipher ecipher;
-  private Cipher dcipher;
-  private SecretKey secret;
-  private byte[] salt = null;
   private char[] passPhrase = null;
   private String alg = "AES";
   private String pbeAlg = "PBKDF2WithHmacSHA1";
@@ -57,60 +49,12 @@ public class ConfigurableEncryptor {
   private int keyLength = KEY_LENGTH;
  
   public ConfigurableEncryptor(String passPhrase) {
-      try {
-        this.passPhrase = passPhrase.toCharArray();
-        salt = new byte[saltSize];
-        SecureRandom rnd = new SecureRandom();
-        rnd.nextBytes(salt);
-        
-        SecretKey tmp = getKeyFromPassword(passPhrase);
-        secret = new SecretKeySpec (tmp.getEncoded(), alg);
- 
-        ecipher = Cipher.getInstance(transformation);
-        ecipher.init(Cipher.ENCRYPT_MODE, secret);
-       
-        dcipher = Cipher.getInstance(transformation);
-        byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-        dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-      } catch (NoSuchAlgorithmException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (NoSuchPaddingException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidKeyException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidParameterSpecException e) {
-        LOG.failedToEncryptPassphrase( e );
-      } catch (InvalidAlgorithmParameterException e) {
-        LOG.failedToEncryptPassphrase( e );
-      }
-  }
-  
-  ConfigurableEncryptor(SecretKey secret) {
-    try {
-      this.secret = new SecretKeySpec (secret.getEncoded(), alg);
-
-      ecipher = Cipher.getInstance(transformation);
-      ecipher.init(Cipher.ENCRYPT_MODE, secret);
-     
-      dcipher = Cipher.getInstance(transformation);
-      byte[] iv = ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
-      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
-    } catch (NoSuchAlgorithmException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (NoSuchPaddingException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidKeyException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidParameterSpecException e) {
-      LOG.failedToEncryptPassphrase( e );
-    } catch (InvalidAlgorithmParameterException e) {
-      LOG.failedToEncryptPassphrase( e );
-    }
+    this.passPhrase = passPhrase.toCharArray();
   }
 
   public void init(GatewayConfig config) {
     if (config != null) {
-	    String alg = config.getAlgorithm();
+      String alg = config.getAlgorithm();
 	    if (alg != null) {
 		  this.alg = alg;
 	    }
@@ -137,10 +81,6 @@ public class ConfigurableEncryptor {
     }
   }
 
-  public SecretKey getKeyFromPassword(String passPhrase) {
-    return getKeyFromPassword(passPhrase, salt);
-  }
-  
   public SecretKey getKeyFromPassword(String passPhrase, byte[] salt) {
     SecretKeyFactory factory;
     SecretKey key = null;
@@ -158,31 +98,32 @@ public class ConfigurableEncryptor {
   }
 
   public EncryptionResult encrypt(String encrypt) throws Exception {
-      byte[] bytes = encrypt.getBytes("UTF8");
+      byte[] bytes = encrypt.getBytes("UTF-8");
       EncryptionResult atom = encrypt(bytes);
       return atom;
   }
 
   public EncryptionResult encrypt(byte[] plain) throws Exception {
-    EncryptionResult atom = new EncryptionResult(salt, ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
ecipher.doFinal(plain));
-    return atom;
-  }
+    byte[] salt = new byte[saltSize];
+    SecureRandom rnd = new SecureRandom();
+    rnd.nextBytes(salt);
 
-  public String decrypt(String salt, String iv, String cipher) throws Exception {
-    byte[] decrypted = decrypt(salt.getBytes("UTF8"), iv.getBytes("UTF8"), cipher.getBytes("UTF8"));
-    return new String(decrypted, "UTF8");
+    SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
+    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), alg);
+    Cipher ecipher = Cipher.getInstance(transformation);
+    ecipher.init(Cipher.ENCRYPT_MODE, secret);
+    EncryptionResult atom = new EncryptionResult(salt,
+        ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
+        ecipher.doFinal(plain));
+    return atom;
   }
 
   public byte[] decrypt(byte[] salt, byte[] iv, byte[] encrypt) throws Exception {
     SecretKey tmp = getKeyFromPassword(new String(passPhrase), salt);
-    secret = new SecretKeySpec(tmp.getEncoded(), alg);
+    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), alg);
     
+    Cipher dcipher = Cipher.getInstance(transformation);
     dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
     return dcipher.doFinal(encrypt);
   }
-  
-  public byte[] decrypt(byte[] encrypt) throws Exception {
-    dcipher.init(Cipher.DECRYPT_MODE, secret);
-    return dcipher.doFinal(encrypt);
-  }
 }


Mime
View raw message