Commit c8afb035 authored by Tom Evans's avatar Tom Evans Committed by tevans

OF-714: Added support for optional property encryption

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@14008 b35dd754-fafc-0310-a699-88a17e54d16e
parent 32a68a5d
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file stores security-related properties needed by Openfire.
You may edit this file to manage encrypted properties and
encryption configuration value. Note however that you should not
edit this file while Openfire is running, or it may be overwritten.
It is important to note that Openfire will store encrypted property
values securely "at rest" (e.g. in the database or XML), but the
values will be managed as clear text strings in memory at runtime for
interoperability and performance reasons. Encrypted property values
are not visible via the Openfire console, but they may be edited or
deleted as needed.
-->
<security>
<encrypt>
<!-- This can be set to "AES" or "Blowfish" (default) at setup time -->
<algorithm>Blowfish</algorithm>
<key>
<!--
If this is a new server setup, you may set a custom encryption key
by setting a value for the <new /> encryption key element only.
To change the encryption key, provide values for both new and old
encryption keys here. The "old" key must match the unencrypted value
of the "current" key. The server will update the existing property
values in the database, re-encrypting them using the new key. After
the encrypted properties have been updated, the new key will itself
be encrypted and re-written into this file as <current />.
Note that if the current encryption key becomes invalid, any property
values secured by the original key will be inaccessible as well.
The key value can be any string, and it will be hashed, filled, and/or
truncated to produce a compatible key for the corresponding algorithm.
Note that leading and trailing spaces will be ignored. A strong key
will contain sixteen characters or more.
<old></old>
<new></new>
-->
<current />
</key>
<property>
<!--
This list includes the names of properties that have been marked for
encryption. Any XML properties (from openfire.xml) that are listed here
will be encrypted automatically upon first use. Other properties
(already in the database) can be added to this list at runtime via the
"System Properties" page in the Openfire console.
-->
<name>database.defaultProvider.username</name>
<name>database.defaultProvider.password</name>
<name>ldap.adminDN</name>
<name>ldap.adminPassword</name>
<name>clearspace.uri</name>
<name>clearspace.sharedSecret</name>
</property>
</encrypt>
<!--
Any other property defined in this file will be treated as an encrypted
property. The value (in clear text) will be encrypted and migrated into
the Openfire database during the next startup. The property name will
be added to the list of encrypted properties and the clear text value
will be removed from this file.
<foo><bar>Secr3t$tr1ng!</bar></foo>
-->
</security>
......@@ -518,6 +518,23 @@
## Added key: 'session.details.node'
## Added key: 'session.details.local'
## Added key: 'session.details.remote'
##
## 3.9.2
## Added key: 'server.properties.encryption'
## Added key: 'server.properties.encrypted'
## Added key: 'server.properties.encrypt'
## Added key: 'server.properties.alt_encrypt'
## Added key: 'server.properties.encrypt_property_true'
## Added key: 'server.properties.encrypt_property_false'
## Added key: 'setup.host.settings.encryption_algorithm'
## Added key: 'setup.host.settings.encryption_algorithm_info'
## Added key: 'setup.host.settings.encryption_aes'
## Added key: 'setup.host.settings.encryption_blowfish'
## Added key: 'setup.host.settings.encryption_key'
## Added key: 'setup.host.settings.encryption_key_info'
## Added key: 'setup.host.settings.encryption_key_invalid'
## Added key: 'server.properties.delete_confirm'
## Added key: 'server.properties.encrypt_confirm'
# Openfire
......@@ -1499,7 +1516,7 @@ server.db_stats.no_queries=No queries
# Server properties Page
server.properties.title=System Properties
server.properties.info=Below is a list of the system properties. Values for password sensitive fields are \
server.properties.info=Below is a list of the system properties. Values for encrypted and sensitive fields are \
hidden. Long property names and values are clipped. Hold your mouse over the property name to see \
the full value or to see both the full name and value, click the edit icon next to the property.
server.properties.system=System Properties
......@@ -1519,6 +1536,15 @@ server.properties.new_property=Add new property
server.properties.enter_property_name=Please enter a valid property name.
server.properties.enter_property_value=Please enter a property value.
server.properties.max_character=1000 character max.
server.properties.encryption=Property Encryption
server.properties.encrypted=Property encrypted successfully.
server.properties.encrypt=Encrypt
server.properties.alt_encrypt=Click to encrypt this property
server.properties.alt_encrypted=Property is encrypted
server.properties.encrypt_property_true=Encrypt this property value
server.properties.encrypt_property_false=Do not encrypt this property value
server.properties.delete_confirm=Are you sure you want to delete this property?
server.properties.encrypt_confirm=Are you sure you want to encrypt this property?
# Server props Page
......@@ -2145,6 +2171,13 @@ setup.host.settings.secure_port=Secure Admin Console Port:
setup.host.settings.invalid_port=Invalid port number
setup.host.settings.port_number=Port number for the web-based admin console (default is 9090).
setup.host.settings.secure_port_number=Port number for the web-based admin console through SSL (default is 9091).
setup.host.settings.encryption_algorithm=Property Encryption via:
setup.host.settings.encryption_algorithm_info=Select an encryption engine/algorithm to use when encrypting properties.
setup.host.settings.encryption_aes=AES
setup.host.settings.encryption_blowfish=Blowfish
setup.host.settings.encryption_key=Property Encryption Key:
setup.host.settings.encryption_key_info=For additional security, you may optionally define a custom encryption key.
setup.host.settings.encryption_key_invalid=You must input the same encryption key value twice to ensure that you have typed the hidden value correctly.
# Setup index Page
......
package org.jivesoftware.util;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class providing symmetric AES encryption/decryption. To strengthen
* the encrypted result, use the {@link #setKey} method to provide a custom
* key prior to invoking the {@link #encrypt} or {@link #decrypt} methods.
*
* @author Tom Evans
*/
public class AesEncryptor implements Encryptor {
private static final Logger log = LoggerFactory.getLogger(AesEncryptor.class);
private static final String ALGORITHM = "AES/CBC/PKCS7Padding";
private static final byte[] INIT_PARM =
{
(byte)0xcd, (byte)0x91, (byte)0xa7, (byte)0xc5,
(byte)0x27, (byte)0x8b, (byte)0x39, (byte)0xe0,
(byte)0xfa, (byte)0x72, (byte)0xd0, (byte)0x29,
(byte)0x83, (byte)0x65, (byte)0x9d, (byte)0x74
};
private static final byte[] DEFAULT_KEY =
{
(byte)0xf2, (byte)0x46, (byte)0x5d, (byte)0x2a,
(byte)0xd1, (byte)0x73, (byte)0x0b, (byte)0x18,
(byte)0xcb, (byte)0x86, (byte)0x95, (byte)0xa3,
(byte)0xb1, (byte)0xe5, (byte)0x89, (byte)0x27
};
private static boolean isInitialized = false;
private byte[] cipherKey = null;
/** Default constructor */
public AesEncryptor() { initialize(); }
/** Custom key constructor */
public AesEncryptor(String key) {
initialize();
setKey(key);
}
/* (non-Javadoc)
* @see org.jivesoftware.util.Encryptor#encrypt(java.lang.String)
*/
@Override
public String encrypt(String value)
{
if (value == null) { return null; }
byte [] bytes = null;
try { bytes = value.getBytes("UTF-8"); }
catch (UnsupportedEncodingException uee) { bytes = value.getBytes(); }
return Base64.encodeBytes( cipher(bytes, getKey(), Cipher.ENCRYPT_MODE) );
}
/* (non-Javadoc)
* @see org.jivesoftware.util.Encryptor#decrypt(java.lang.String)
*/
@Override
public String decrypt(String value)
{
if (value == null) { return null; }
byte [] bytes = cipher(Base64.decode(value), getKey(), Cipher.DECRYPT_MODE);
if (bytes == null) { return null; }
String result = null;
try { result = new String(bytes,"UTF-8"); }
catch (UnsupportedEncodingException uee) { result = new String(bytes); }
return result;
}
/**
* Symmetric encrypt/decrypt routine.
*
* @param attribute The value to be converted
* @param key The encryption key
* @param mode The cipher mode (encrypt or decrypt)
* @return The converted attribute, or null if conversion fails
*/
private byte [] cipher(byte [] attribute, byte [] key, int mode)
{
byte [] result = null;
try
{
// Create AES encryption key
Key aesKey = new SecretKeySpec(key, "AES");
// Create AES Cipher
Cipher aesCipher = Cipher.getInstance(ALGORITHM);
// Initialize AES Cipher and convert
aesCipher.init(mode, aesKey, new IvParameterSpec(INIT_PARM));
result = aesCipher.doFinal(attribute);
}
catch (Exception e)
{
log.error("AES cipher failed", e);
}
return result;
}
/**
* Return the encryption key. This will return the user-defined
* key (if available) or a default encryption key.
*
* @return The encryption key
*/
private byte [] getKey()
{
return cipherKey == null ? DEFAULT_KEY : cipherKey;
}
/**
* Set the encryption key. This will apply the user-defined key,
* truncated or filled (via the default key) as needed to meet
* the key length specifications.
*
* @param key The encryption key
*/
private void setKey(byte [] key)
{
cipherKey = editKey(key);
}
/* (non-Javadoc)
* @see org.jivesoftware.util.Encryptor#setKey(java.lang.String)
*/
@Override
public void setKey(String key)
{
if (key == null) {
cipherKey = null;
return;
}
byte [] bytes = null;
try { bytes = key.getBytes("UTF-8"); }
catch (UnsupportedEncodingException uee) { bytes = key.getBytes(); }
setKey(editKey(bytes));
}
/**
* Validates an optional user-defined encryption key. Only the
* first sixteen bytes of the input array will be used for the key.
* It will be filled (if necessary) to a minimum length of sixteen.
*
* @param key The user-defined encryption key
* @return A valid encryption key, or null
*/
private byte [] editKey(byte [] key)
{
if (key == null) { return null; }
byte [] result = new byte [DEFAULT_KEY.length];
for (int x=0; x<DEFAULT_KEY.length; x++)
{
result[x] = x < key.length ? key[x] : DEFAULT_KEY[x];
}
return result;
}
/** Installs the required security provider(s) */
private synchronized void initialize()
{
if (!isInitialized)
{
try
{
Security.addProvider(new BouncyCastleProvider());
isInitialized = true;
}
catch (Throwable t)
{
log.warn("JCE provider failure; unable to load BC", t);
}
}
}
/* */
}
......@@ -26,12 +26,20 @@ import org.slf4j.LoggerFactory;
* @author Markus Hahn <markus_hahn@gmx.net>
* @author Gaston Dombiak
*/
public class Blowfish {
public class Blowfish implements Encryptor {
private static final Logger Log = LoggerFactory.getLogger(Blowfish.class);
private BlowfishCBC m_bfish;
private static Random m_rndGen = new Random();
private static final String DEFAULT_KEY = "Blowfish-CBC";
/**
* Creates a new Blowfish object using the default key
*/
public Blowfish() {
setKey(DEFAULT_KEY);
}
/**
* Creates a new Blowfish object using the specified key (oversized
......@@ -40,19 +48,7 @@ public class Blowfish {
* @param password the password (treated as a real unicode array)
*/
public Blowfish(String password) {
// hash down the password to a 160bit key
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA1");
digest.update(password.getBytes());
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
// setup the encryptor (use a dummy IV)
m_bfish = new BlowfishCBC(digest.digest(), 0);
digest.reset();
setKey(password);
}
/**
......@@ -64,6 +60,7 @@ public class Blowfish {
* @return encrypted string in binhex format
*/
public String encryptString(String sPlainText) {
if (sPlainText == null) { return null; }
// get the IV
long lCBCIV;
synchronized (m_rndGen)
......@@ -1484,5 +1481,36 @@ public class Blowfish {
return sbuf.toString();
}
// Encryptor interface
@Override
public String encrypt(String value) {
return this.encryptString(value);
}
@Override
public String decrypt(String value) {
return this.decryptString(value);
}
@Override
public void setKey(String key) {
String password = key == null ? DEFAULT_KEY : key;
// hash down the password to a 160bit key
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA1");
digest.update(password.getBytes());
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
// setup the encryptor (use a dummy IV)
m_bfish = new BlowfishCBC(digest.digest(), 0);
digest.reset();
}
}
package org.jivesoftware.util;
public interface Encryptor {
/**
* Encrypt a clear text String.
*
* @param value The clear text attribute
* @return The encrypted attribute, or null
*/
public abstract String encrypt(String value);
/**
* Decrypt an encrypted String.
*
* @param value The encrypted attribute in Base64 encoding
* @return The clear text attribute, or null
*/
public abstract String decrypt(String value);
/**
* Set the encryption key. This will apply the user-defined key,
* truncated or filled (via the default key) as needed to meet
* the key length specifications.
*
* @param key The encryption key
*/
public abstract void setKey(String key);
}
\ No newline at end of file
......@@ -51,12 +51,7 @@ public class JiveProperties implements Map<String, String> {
private static final String UPDATE_PROPERTY = "UPDATE ofProperty SET propValue=? WHERE name=?";
private static final String DELETE_PROPERTY = "DELETE FROM ofProperty WHERE name LIKE ?";
private static class JivePropertyHolder {
private static final JiveProperties instance = new JiveProperties();
static {
instance.init();
}
}
private static JiveProperties instance = null;
private Map<String, String> properties;
......@@ -65,16 +60,19 @@ public class JiveProperties implements Map<String, String> {
*
* @return an instance of JiveProperties.
*/
public static JiveProperties getInstance() {
return JivePropertyHolder.instance;
}
private JiveProperties() {
public synchronized static JiveProperties getInstance() {
if (instance == null) {
JiveProperties props = new JiveProperties();
props.init();
instance = props;
}
return instance;
}
private JiveProperties() { }
/**
* For internal use only. This method allows for the reloading of all properties from the
* values in the datatabase. This is required since it's quite possible during the setup
* values in the database. This is required since it's quite possible during the setup
* process that a database connection will not be available till after this class is
* initialized. Thus, if there are existing properties in the database we will want to reload
* this class after the setup process has been completed.
......@@ -192,7 +190,7 @@ public class JiveProperties implements Map<String, String> {
PropertyEventDispatcher.dispatchEvent((String)key, PropertyEventDispatcher.EventType.property_deleted, params);
// Send update to other cluster members.
CacheFactory.doClusterTask(PropertyClusterEventTask.createDeteleTask((String) key));
CacheFactory.doClusterTask(PropertyClusterEventTask.createDeleteTask((String) key));
return value;
}
......@@ -284,13 +282,14 @@ public class JiveProperties implements Map<String, String> {
}
private void insertProperty(String name, String value) {
Encryptor encryptor = getEncryptor();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_PROPERTY);
pstmt.setString(1, name);
pstmt.setString(2, value);
pstmt.setString(2, JiveGlobals.isPropertyEncrypted(name) ? encryptor.encrypt(value) : value);
pstmt.executeUpdate();
}
catch (SQLException e) {
......@@ -302,12 +301,13 @@ public class JiveProperties implements Map<String, String> {
}
private void updateProperty(String name, String value) {
Encryptor encryptor = getEncryptor();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PROPERTY);
pstmt.setString(1, value);
pstmt.setString(1, JiveGlobals.isPropertyEncrypted(name) ? encryptor.encrypt(value) : value);
pstmt.setString(2, name);
pstmt.executeUpdate();
}
......@@ -337,6 +337,7 @@ public class JiveProperties implements Map<String, String> {
}
private void loadProperties() {
Encryptor encryptor = getEncryptor();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
......@@ -347,7 +348,17 @@ public class JiveProperties implements Map<String, String> {
while (rs.next()) {
String name = rs.getString(1);
String value = rs.getString(2);
properties.put(name, value);
if (JiveGlobals.isPropertyEncrypted(name)) {
try {
value = encryptor.decrypt(value);
} catch (Exception ex) {
Log.error("Failed to load encrypted property value for " + name, ex);
value = null;
}
}
if (value != null) {
properties.put(name, value);
}
}
}
catch (Exception e) {
......@@ -357,4 +368,8 @@ public class JiveProperties implements Map<String, String> {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
private Encryptor getEncryptor() {
return JiveGlobals.getPropertyEncryptor();
}
}
\ No newline at end of file
......@@ -46,7 +46,7 @@ public class PropertyClusterEventTask implements ClusterTask {
return task;
}
public static PropertyClusterEventTask createDeteleTask(String key) {
public static PropertyClusterEventTask createDeleteTask(String key) {
PropertyClusterEventTask task = new PropertyClusterEventTask();
task.event = Type.deleted;
task.key = key;
......
......@@ -19,6 +19,7 @@
*/
package org.jivesoftware.util.cache;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
......@@ -70,7 +71,7 @@ public class CacheFactory {
private static String localCacheFactoryClass;
private static String clusteredCacheFactoryClass;
private static CacheFactoryStrategy cacheFactoryStrategy;
private static CacheFactoryStrategy cacheFactoryStrategy = new DefaultLocalCacheStrategy();
private static CacheFactoryStrategy localCacheFactoryStrategy;
private static CacheFactoryStrategy clusteredCacheFactoryStrategy;
private static Thread statsThread;
......@@ -440,6 +441,8 @@ public class CacheFactory {
clusteredCacheFactoryStrategy = (CacheFactoryStrategy) Class.forName(
clusteredCacheFactoryClass, true,
getClusteredCacheStrategyClassLoader()).newInstance();
} catch (NoClassDefFoundError e) {
log.warn("Clustered cache factory strategy " + clusteredCacheFactoryClass + " not found");
} catch (Exception e) {
log.warn("Clustered cache factory strategy " + clusteredCacheFactoryClass + " not found");
}
......@@ -626,10 +629,18 @@ public class CacheFactory {
}
PluginClassLoader pluginLoader = pluginManager.getPluginClassloader(plugin);
if (pluginLoader != null) {
if (log.isDebugEnabled()) {
StringBuffer pluginLoaderDetails = new StringBuffer("Clustering plugin class loader: ");
pluginLoaderDetails.append(pluginLoader.getClass().getName());
for (URL url : pluginLoader.getURLs()) {
pluginLoaderDetails.append("\n\t").append(url.toExternalForm());
}
log.debug(pluginLoaderDetails.toString());
}
return pluginLoader;
}
else {
log.debug("CacheFactory - Unable to find a Plugin that provides clustering support.");
log.warn("CacheFactory - Unable to find a Plugin that provides clustering support.");
return Thread.currentThread().getContextClassLoader();
}
}
......
package org.jivesoftware.util;
import java.util.UUID;
import junit.framework.TestCase;
import org.junit.Test;
public class AesEncryptorTest extends TestCase {
@Test
public void testEncryptionUsingDefaultKey() {
String test = UUID.randomUUID().toString();
Encryptor encryptor = new AesEncryptor();
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionUsingCustomKey() {
String test = UUID.randomUUID().toString();
Encryptor encryptor = new AesEncryptor(UUID.randomUUID().toString());
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionForEmptyString() {
String test = "";
Encryptor encryptor = new AesEncryptor();
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionForNullString() {
String test = null;
Encryptor encryptor = new AesEncryptor();
String b64Encrypted = encryptor.encrypt(test);
assertNull(b64Encrypted);
}
}
package org.jivesoftware.util;
import java.util.UUID;
import junit.framework.TestCase;
import org.junit.Test;
public class BlowfishEncryptorTest extends TestCase {
@Test
public void testEncryptionUsingDefaultKey() {
String test = UUID.randomUUID().toString();
Encryptor encryptor = new Blowfish();
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionUsingCustomKey() {
String test = UUID.randomUUID().toString();
Encryptor encryptor = new Blowfish(UUID.randomUUID().toString());
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionForEmptyString() {
String test = "";
Encryptor encryptor = new Blowfish();
String b64Encrypted = encryptor.encrypt(test);
assertFalse(test.equals(b64Encrypted));
assertEquals(test, encryptor.decrypt(b64Encrypted));
}
@Test
public void testEncryptionForNullString() {
String test = null;
Encryptor encryptor = new Blowfish();
String b64Encrypted = encryptor.encrypt(test);
assertNull(b64Encrypted);
}
}
src/web/images/add-16x16.gif

615 Bytes | W: | H:

src/web/images/add-16x16.gif

614 Bytes | W: | H:

src/web/images/add-16x16.gif
src/web/images/add-16x16.gif
src/web/images/add-16x16.gif
src/web/images/add-16x16.gif
  • 2-up
  • Swipe
  • Onion skin
......@@ -63,6 +63,7 @@
String propName = ParamUtils.getParameter(request,"propName");
String propValue = ParamUtils.getParameter(request,"propValue",true);
boolean edit = ParamUtils.getBooleanParameter(request,"edit");
boolean encrypt = ParamUtils.getBooleanParameter(request,"encrypt");
boolean save = request.getParameter("save") != null;
boolean delete = ParamUtils.getBooleanParameter(request,"del");
......@@ -81,6 +82,16 @@
}
}
if (encrypt) {
if (propName != null) {
JiveGlobals.setPropertyEncrypted(propName, true);
// Log the event
webManager.logEvent("encrypted server property "+propName, null);
response.sendRedirect("server-properties.jsp?encryptsuccess=true");
return;
}
}
Map<String, String> errors = new HashMap<String, String>();
if (save) {
if (propName == null || "".equals(propName.trim()) || propName.startsWith("\"")) {
......@@ -93,6 +104,7 @@
errors.put("propValueLength","");
}
if (errors.size() == 0) {
JiveGlobals.setPropertyEncrypted(propName, encrypt);
JiveGlobals.setProperty(propName, propValue);
// Log the event
webManager.logEvent("set server property "+propName, propName+" = "+propValue);
......@@ -166,6 +178,19 @@
</table>
</div><br>
<% } else if ("true".equals(request.getParameter("encryptsuccess"))) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr><td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">
<fmt:message key="server.properties.encrypted" />
</td></tr>
</tbody>
</table>
</div><br>
<% } %>
<% if (edit) { %>
......@@ -205,8 +230,17 @@ function doedit(propName) {
document.propform.action = document.propform.action + '#edit';
document.propform.submit();
}
function doencrypt(propName) {
var doencrypt = confirm('<fmt:message key="server.properties.encrypt_confirm" />');
if (doencrypt) {
document.propform.propName.value = propName;
document.propform.encrypt.value = 'true';
document.propform.action = document.propform.action + '#encrypt';
document.propform.submit();
}
}
function dodelete(propName) {
var dodelete = confirm('Are you sure you want to delete this property?');
var dodelete = confirm('<fmt:message key="server.properties.delete_confirm" />');
if (dodelete) {
document.propform.propName.value = propName;
document.propform.del.value = 'true';
......@@ -221,6 +255,7 @@ function dodelete(propName) {
<form action="server-properties.jsp" method="post" name="propform">
<input type="hidden" name="edit" value="">
<input type="hidden" name="encrypt" value="">
<input type="hidden" name="del" value="">
<input type="hidden" name="propName" value="">
......@@ -239,6 +274,7 @@ function dodelete(propName) {
<th nowrap><fmt:message key="server.properties.name" /></th>
<th nowrap><fmt:message key="server.properties.value" /></th>
<th style="text-align:center;"><fmt:message key="server.properties.edit" /></th>
<th style="text-align:center;"><fmt:message key="server.properties.encrypt" /></th>
<th style="text-align:center;"><fmt:message key="global.delete" /></th>
</tr>
</thead>
......@@ -269,9 +305,8 @@ function dodelete(propName) {
</td>
<td>
<div class="hidebox" style="width:300px;">
<% if (n.toLowerCase().indexOf("passwd") > -1 ||
n.toLowerCase().indexOf("password") > -1 ||
n.toLowerCase().indexOf("cookiekey") > -1) { %>
<% if (JiveGlobals.isPropertyEncrypted(n) ||
JiveGlobals.isPropertySensitive(n)) { %>
<span style="color:#999;"><i>hidden</i></span>
<% } else { %>
<span title="<%= ("".equals(v) ? "&nbsp;" : v) %>"><%= ("".equals(v) ? "&nbsp;" : v) %></span>
......@@ -283,6 +318,15 @@ function dodelete(propName) {
alt="<fmt:message key="server.properties.alt_edit" />" border="0"></a
>
</td>
<td align="center"><%
if (!JiveGlobals.isPropertyEncrypted(n)) { %>
<a href="#" onclick="doencrypt('<%= StringUtils.replace(StringUtils.escapeHTMLTags(n),"'","''") %>');" >
<img src="images/add-16x16.gif" width="16" height="16" alt="<fmt:message key="server.properties.alt_encrypt" />" border="0"></a><%
} else { %>
<img src="images/lock.gif" width="16" height="16" alt="<fmt:message key="server.properties.alt_encrypted" />" border="0"><%
} %>
</td>
<td align="center"><a href="#" onclick="return dodelete('<%= StringUtils.replace(StringUtils.escapeHTMLTags(n),"'","''") %>');"
><img src="images/delete-16x16.gif" width="16" height="16"
alt="<fmt:message key="server.properties.alt_delete" />" border="0"></a
......@@ -345,6 +389,7 @@ function dodelete(propName) {
<fmt:message key="server.properties.value" />:
</td>
<td>
<% if (JiveGlobals.isPropertyEncrypted(propName) || JiveGlobals.isPropertySensitive(propName)) { propValue = null; } %>
<textarea cols="45" rows="5" name="propValue" wrap="virtual"><%= (propValue != null ? StringUtils.escapeHTMLTags(propValue, false) : "") %></textarea>
<% if (errors.containsKey("propValue")) { %>
......@@ -358,6 +403,15 @@ function dodelete(propName) {
<% } %>
</td>
</tr>
<tr valign="top">
<td>
<fmt:message key="server.properties.encryption" />:
</td>
<td>
<input type="radio" name="encrypt" value="true" <%= JiveGlobals.isPropertyEncrypted(propName) ? "checked" : "" %> /><fmt:message key="server.properties.encrypt_property_true"/><br/>
<input type="radio" name="encrypt" value="false" <%= JiveGlobals.isPropertyEncrypted(propName) ? "" : "checked" %>/><fmt:message key="server.properties.encrypt_property_false"/>
</td>
</tr>
</tbody>
<tfoot>
<tr>
......
......@@ -29,6 +29,8 @@
int embeddedPort = ParamUtils.getIntParameter(request, "embeddedPort", Integer.MIN_VALUE);
int securePort = ParamUtils.getIntParameter(request, "securePort", Integer.MIN_VALUE);
boolean sslEnabled = ParamUtils.getBooleanParameter(request, "sslEnabled", true);
String encryptionAlgorithm = ParamUtils.getParameter(request, "encryptionAlgorithm");
String encryptionKey = ParamUtils.getParameter(request, "encryptionKey");
boolean doContinue = request.getParameter("continue") != null;
......@@ -55,6 +57,14 @@
else if (securePort < 0) {
securePort = -1;
}
if (encryptionKey != null) {
// ensure the same key value was provided twice
String repeat = ParamUtils.getParameter(request, "encryptionKey1");
if (!encryptionKey.equals(repeat)) {
errors.put("encryptionKey", "encryptionKey");
}
}
} else {
embeddedPort = -1;
securePort = -1;
......@@ -73,6 +83,9 @@
xmlSettings.put("adminConsole.securePort", Integer.toString(securePort));
session.setAttribute("xmlSettings", xmlSettings);
JiveGlobals.setupPropertyEncryptionAlgorithm(encryptionAlgorithm);
JiveGlobals.setupPropertyEncryptionKey(encryptionKey);
// Successful, so redirect
response.sendRedirect("setup-datasource-settings.jsp");
return;
......@@ -166,6 +179,31 @@
<% } %>
</td>
</tr>
<tr valign="top">
<td width="1%" nowrap align="right">
<fmt:message key="setup.host.settings.encryption_algorithm" />
</td>
<td width="99%">
<span class="jive-setup-helpicon" onmouseover="domTT_activate(this, event, 'content', '<fmt:message key="setup.host.settings.encryption_algorithm_info" />', 'styleClass', 'jiveTooltip', 'trail', true, 'delay', 300, 'lifetime', 8000);"></span><br /><br />
<input type="radio" name="encryptionAlgorithm" value="Blowfish" checked><fmt:message key="setup.host.settings.encryption_blowfish" /><br /><br />
<input type="radio" name="encryptionAlgorithm" value="AES"><fmt:message key="setup.host.settings.encryption_aes" /><br /><br />
</td>
</tr>
<tr valign="top">
<td width="1%" nowrap align="right">
<fmt:message key="setup.host.settings.encryption_key" />
</td>
<td width="99%">
<input type="password" size="50" name="encryptionKey" /><br /><br />
<input type="password" size="50" name="encryptionKey1" />
<span class="jive-setup-helpicon" onmouseover="domTT_activate(this, event, 'content', '<fmt:message key="setup.host.settings.encryption_key_info" />', 'styleClass', 'jiveTooltip', 'trail', true, 'delay', 300, 'lifetime', 8000);"></span>
<% if (errors.get("encryptionKey") != null) { %>
<span class="jive-error-text">
<fmt:message key="setup.host.settings.encryption_key_invalid" />
</span>
<% } %>
</td>
</tr>
<% } %>
</table>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment