diff --git a/scm-core/src/main/java/sonia/scm/security/CipherSingleton.java b/scm-core/src/main/java/sonia/scm/security/CipherUtil.java similarity index 57% rename from scm-core/src/main/java/sonia/scm/security/CipherSingleton.java rename to scm-core/src/main/java/sonia/scm/security/CipherUtil.java index 3fde6cf6c9..c516cc7a8f 100644 --- a/scm-core/src/main/java/sonia/scm/security/CipherSingleton.java +++ b/scm-core/src/main/java/sonia/scm/security/CipherUtil.java @@ -33,15 +33,78 @@ package sonia.scm.security; +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.SCMContext; +import sonia.scm.util.ServiceUtil; + /** * * @author Sebastian Sdorra + * @since 1.7 */ -public class CipherSingleton +public class CipherUtil { /** Field description */ - private static CipherHandler cipherHandler; + private static volatile CipherUtil instance; + + //~--- constructors --------------------------------------------------------- + + private KeyGenerator keyGenerator; + + /** + * Constructs ... + * + */ + private CipherUtil() + { + keyGenerator = ServiceUtil.getService(KeyGenerator.class); + + if (keyGenerator == null) + { + keyGenerator = new UUIDKeyGenerator(); + } + + cipherHandler = ServiceUtil.getService(CipherHandler.class); + + if (cipherHandler == null) + { + cipherHandler = new DefaultCipherHandler(SCMContext.getContext(), + keyGenerator); + } + } + + public KeyGenerator getKeyGenerator() + { + return keyGenerator; + } + + + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public static CipherUtil getInstance() + { + if (instance == null) + { + synchronized (CipherUtil.class) + { + if (instance == null) + { + instance = new CipherUtil(); + } + } + } + + return instance; + } //~--- methods -------------------------------------------------------------- @@ -53,13 +116,8 @@ public class CipherSingleton * * @return */ - public static String decode(String value) + public String decode(String value) { - if (cipherHandler == null) - { - throw new CipherException("CipherSingleton is not initialized"); - } - return cipherHandler.decode(value); } @@ -71,24 +129,26 @@ public class CipherSingleton * * @return */ - public static String encode(String value) + public String encode(String value) { - if (cipherHandler == null) - { - throw new CipherException("CipherSingleton is not initialized"); - } - return cipherHandler.encode(value); } + //~--- get methods ---------------------------------------------------------- + /** * Method description * * - * @param handler + * @return */ - public static void init(CipherHandler handler) + public CipherHandler getCipherHandler() { - cipherHandler = handler; + return cipherHandler; } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private CipherHandler cipherHandler; } diff --git a/scm-webapp/src/main/java/sonia/scm/security/DefaultCipherHandler.java b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java similarity index 96% rename from scm-webapp/src/main/java/sonia/scm/security/DefaultCipherHandler.java rename to scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java index 649f698036..64f81be6fd 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/DefaultCipherHandler.java +++ b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java @@ -35,9 +35,6 @@ package sonia.scm.security; //~--- non-JDK imports -------------------------------------------------------- -import com.google.inject.Inject; -import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,8 +66,8 @@ import javax.crypto.spec.SecretKeySpec; /** * * @author Sebastian Sdorra + * @since 1.7 */ -@Singleton public class DefaultCipherHandler implements CipherHandler { @@ -117,26 +114,30 @@ public class DefaultCipherHandler implements CipherHandler * @param keyGenerator * * - * @throws IOException */ - @Inject public DefaultCipherHandler(SCMContextProvider context, KeyGenerator keyGenerator) - throws IOException { File configDirectory = new File(context.getBaseDirectory(), "config"); IOUtil.mkdirs(configDirectory); cipherKeyFile = new File(configDirectory, CIPHERKEY_FILENAME); - if (cipherKeyFile.exists()) + try { - loadKey(); + if (cipherKeyFile.exists()) + { + loadKey(); + } + else + { + key = keyGenerator.createKey().toCharArray(); + storeKey(); + } } - else + catch (IOException ex) { - key = keyGenerator.createKey().toCharArray(); - storeKey(); + throw new CipherException("could not create CipherHandler", ex); } } diff --git a/scm-webapp/src/main/java/sonia/scm/security/UUIDKeyGenerator.java b/scm-core/src/main/java/sonia/scm/security/UUIDKeyGenerator.java similarity index 98% rename from scm-webapp/src/main/java/sonia/scm/security/UUIDKeyGenerator.java rename to scm-core/src/main/java/sonia/scm/security/UUIDKeyGenerator.java index 1e7e60bad5..361f5e839d 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/UUIDKeyGenerator.java +++ b/scm-core/src/main/java/sonia/scm/security/UUIDKeyGenerator.java @@ -36,6 +36,7 @@ package sonia.scm.security; //~--- JDK imports ------------------------------------------------------------ import java.util.UUID; +import sonia.scm.security.KeyGenerator; /** * diff --git a/scm-core/src/main/java/sonia/scm/xml/XmlCipherStringAdapter.java b/scm-core/src/main/java/sonia/scm/xml/XmlCipherStringAdapter.java index 77bac02189..09f32ff38d 100644 --- a/scm-core/src/main/java/sonia/scm/xml/XmlCipherStringAdapter.java +++ b/scm-core/src/main/java/sonia/scm/xml/XmlCipherStringAdapter.java @@ -35,7 +35,7 @@ package sonia.scm.xml; //~--- non-JDK imports -------------------------------------------------------- -import sonia.scm.security.CipherSingleton; +import sonia.scm.security.CipherUtil; //~--- JDK imports ------------------------------------------------------------ @@ -62,7 +62,7 @@ public class XmlCipherStringAdapter extends XmlAdapter @Override public String marshal(String v) throws Exception { - return CipherSingleton.encode(v); + return CipherUtil.getInstance().encode(v); } /** @@ -78,6 +78,6 @@ public class XmlCipherStringAdapter extends XmlAdapter @Override public String unmarshal(String v) throws Exception { - return CipherSingleton.decode(v); + return CipherUtil.getInstance().decode(v); } } diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index a3f5716b8d..c3062ea369 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -58,7 +58,7 @@ import java.util.List; import javax.servlet.ServletContextEvent; import sonia.scm.security.CipherHandler; -import sonia.scm.security.CipherSingleton; +import sonia.scm.security.CipherUtil; /** * @@ -145,10 +145,6 @@ public class ScmContextListener extends GuiceServletContextListener injector = Guice.createInjector(moduleList); SCMContextProvider context = SCMContext.getContext(); - - // init CipherSingleton - CipherHandler ch = injector.getInstance(CipherHandler.class); - CipherSingleton.init(ch); // init StoreFactory injector.getInstance(StoreFactory.class).init(context); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index b85df81d1e..9a8f763d4c 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -65,12 +65,11 @@ import sonia.scm.repository.RepositoryBrowserUtil; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.xml.XmlRepositoryManager; import sonia.scm.security.CipherHandler; -import sonia.scm.security.DefaultCipherHandler; +import sonia.scm.security.CipherUtil; import sonia.scm.security.EncryptionHandler; import sonia.scm.security.KeyGenerator; import sonia.scm.security.MessageDigestEncryptionHandler; import sonia.scm.security.SecurityContext; -import sonia.scm.security.UUIDKeyGenerator; import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.StoreFactory; import sonia.scm.template.FreemarkerTemplateHandler; @@ -196,14 +195,15 @@ public class ScmServletModule extends ServletModule bind(SCMContextProvider.class).toInstance(context); ScmConfiguration config = getScmConfiguration(context); + CipherUtil cu = CipherUtil.getInstance(); bind(StoreFactory.class).to(JAXBStoreFactory.class); bind(ScmConfiguration.class).toInstance(config); bind(PluginLoader.class).toInstance(pluginLoader); bind(PluginManager.class).to(DefaultPluginManager.class); - bind(KeyGenerator.class).to(UUIDKeyGenerator.class); + bind(KeyGenerator.class).toInstance(cu.getKeyGenerator()); + bind(CipherHandler.class).toInstance(cu.getCipherHandler()); bind(EncryptionHandler.class).to(MessageDigestEncryptionHandler.class); - bind(CipherHandler.class).to(DefaultCipherHandler.class); bindExtProcessor.bindExtensions(binder()); Class fileSystem = diff --git a/scm-webapp/src/main/java/sonia/scm/util/ScmConfigurationUtil.java b/scm-webapp/src/main/java/sonia/scm/util/ScmConfigurationUtil.java index 39b1c1d2d9..6ee78fb501 100644 --- a/scm-webapp/src/main/java/sonia/scm/util/ScmConfigurationUtil.java +++ b/scm-webapp/src/main/java/sonia/scm/util/ScmConfigurationUtil.java @@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.ConfigurationException; import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; +import sonia.scm.security.CipherUtil; //~--- JDK imports ------------------------------------------------------------ @@ -131,6 +132,13 @@ public class ScmConfigurationUtil Unmarshaller unmarshaller = context.createUnmarshaller(); ScmConfiguration loadedConfig = (ScmConfiguration) unmarshaller.unmarshal(file); + String password = loadedConfig.getProxyPassword(); + + if (Util.isNotEmpty(password)) + { + password = CipherUtil.getInstance().decode(password); + loadedConfig.setProxyPassword(password); + } if (loadedConfig != null) { @@ -168,10 +176,22 @@ public class ScmConfigurationUtil IOUtil.mkdirs(file.getParentFile()); } + ScmConfiguration config = new ScmConfiguration(); + + config.load(configuration); + + String password = config.getProxyPassword(); + + if (Util.isNotEmpty(password)) + { + password = CipherUtil.getInstance().encode(password); + config.setProxyPassword(password); + } + Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - marshaller.marshal(configuration, file); + marshaller.marshal(config, file); configuration.fireChangeEvent(); } catch (Exception ex)