This is an automated email from the ASF dual-hosted git repository.
pradeep pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new d0e5fe9 Ranger-1644-Change the default Crypt Algo to use stronger
cryptographic algo
d0e5fe9 is described below
commit d0e5fe90752b21365d5b86d92936b48ea53c6ab2
Author: mateenmansoori <[email protected]>
AuthorDate: Tue Jul 2 15:37:40 2019 +0530
Ranger-1644-Change the default Crypt Algo to use stronger cryptographic algo
Signed-off-by: Pradeep <[email protected]>
---
.../apache/ranger/plugin/util/PasswordUtils.java | 145 +++++++++++----
.../ranger/plugin/util/PasswordUtilsTest.java | 201 +++++++++++++++++----
.../java/org/apache/ranger/biz/ServiceDBStore.java | 73 ++++----
.../ranger/patch/cliutil/ChangePasswordUtil.java | 1 -
.../ranger/service/RangerServiceService.java | 60 +++---
.../conf.dist/ranger-admin-default-site.xml | 2 +-
.../org/apache/ranger/biz/TestServiceDBStore.java | 83 +++++++++
7 files changed, 417 insertions(+), 148 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
index 6480b17..c08f55d 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
@@ -17,40 +17,51 @@
package org.apache.ranger.plugin.util;
import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
import com.sun.jersey.core.util.Base64;
public class PasswordUtils {
private static final Logger LOG =
LoggerFactory.getLogger(PasswordUtils.class);
- private final String CRYPT_ALGO;
+ private final String cryptAlgo;
private String password;
- private final char[] ENCRYPT_KEY;
- private final byte[] SALT;
- private final int ITERATION_COUNT;
+ private final int iterationCount;
private final char[] encryptKey;
private final byte[] salt;
+ private final byte[] iv;
private static final String LEN_SEPARATOR_STR = ":";
+ public static final String PBE_SHA512_AES_128 =
"PBEWITHHMACSHA512ANDAES_128";
+
public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";
public static final String DEFAULT_ENCRYPT_KEY =
"tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV";
public static final String DEFAULT_SALT = "f77aLYLo";
public static final int DEFAULT_ITERATION_COUNT = 17;
+ public static final byte[] DEFAULT_INITIAL_VECTOR = new byte[16];
- public static String encryptPassword(String aPassword) throws IOException {
- return new PasswordUtils(aPassword).encrypt();
- }
+ public static String encryptPassword(String aPassword) throws
IOException {
+ return build(aPassword).encrypt();
+ }
+
+ public static PasswordUtils build(String aPassword) {
+ return new PasswordUtils(aPassword);
+ }
private String encrypt() throws IOException {
String ret = null;
@@ -61,11 +72,11 @@ public class PasswordUtils {
strToEncrypt = password.length() + LEN_SEPARATOR_STR + password;
}
try {
- Cipher engine = Cipher.getInstance(CRYPT_ALGO);
+ Cipher engine = Cipher.getInstance(cryptAlgo);
PBEKeySpec keySpec = new PBEKeySpec(encryptKey);
- SecretKeyFactory skf = SecretKeyFactory.getInstance(CRYPT_ALGO);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(cryptAlgo);
SecretKey key = skf.generateSecret(keySpec);
- engine.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt,
ITERATION_COUNT));
+ engine.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt,
iterationCount, new IvParameterSpec(iv)));
byte[] encryptedStr = engine.doFinal(strToEncrypt.getBytes());
ret = new String(Base64.encode(encryptedStr));
}
@@ -78,29 +89,36 @@ public class PasswordUtils {
PasswordUtils(String aPassword) {
String[] crypt_algo_array = null;
- int count = 0;
- if (aPassword != null && aPassword.contains(",")) {
- count = StringUtils.countMatches(aPassword, ",");
- crypt_algo_array = aPassword.split(",");
- }
- if (crypt_algo_array != null && crypt_algo_array.length > 4) {
- CRYPT_ALGO = crypt_algo_array[0];
- ENCRYPT_KEY = crypt_algo_array[1].toCharArray();
- SALT = crypt_algo_array[2].getBytes();
- ITERATION_COUNT = Integer.parseInt(crypt_algo_array[3]);
- password = crypt_algo_array[4];
- if (count > 4) {
- for (int i = 5 ; i<=count ; i++){
- password = password + "," + crypt_algo_array[i];
- }
- }
- } else {
- CRYPT_ALGO = DEFAULT_CRYPT_ALGO;
- ENCRYPT_KEY = DEFAULT_ENCRYPT_KEY.toCharArray();
- SALT = DEFAULT_SALT.getBytes();
- ITERATION_COUNT = DEFAULT_ITERATION_COUNT;
- password = aPassword;
- }
+ byte[] SALT;
+ char[] ENCRYPT_KEY;
+ if (aPassword != null && aPassword.contains(",")) {
+ crypt_algo_array =
Lists.newArrayList(Splitter.on(",").split(aPassword)).toArray(new String[0]);
+ }
+ if (crypt_algo_array != null && crypt_algo_array.length > 4) {
+ int index = 0;
+ cryptAlgo = crypt_algo_array[index++]; // 0
+ ENCRYPT_KEY = crypt_algo_array[index++].toCharArray();
// 1
+ SALT = crypt_algo_array[index++].getBytes(); // 2
+ iterationCount =
Integer.parseInt(crypt_algo_array[index++]);// 3
+ if (needsIv(cryptAlgo)) {
+ iv = Base64.decode(crypt_algo_array[index++]);
+ } else {
+ iv = DEFAULT_INITIAL_VECTOR;
+ }
+ password = crypt_algo_array[index++];
+ if (crypt_algo_array.length > index) {
+ for (int i = index; i <
crypt_algo_array.length; i++) {
+ password = password + "," +
crypt_algo_array[i];
+ }
+ }
+ } else {
+ cryptAlgo = DEFAULT_CRYPT_ALGO;
+ ENCRYPT_KEY = DEFAULT_ENCRYPT_KEY.toCharArray();
+ SALT = DEFAULT_SALT.getBytes();
+ iterationCount = DEFAULT_ITERATION_COUNT;
+ iv = DEFAULT_INITIAL_VECTOR;
+ password = aPassword;
+ }
Map<String, String> env = System.getenv();
String encryptKeyStr = env.get("ENCRYPT_KEY");
if (encryptKeyStr == null) {
@@ -116,19 +134,19 @@ public class PasswordUtils {
}
}
- public static String decryptPassword(String aPassword) throws IOException {
- return new PasswordUtils(aPassword).decrypt();
- }
+ public static String decryptPassword(String aPassword) throws
IOException {
+ return build(aPassword).decrypt();
+ }
private String decrypt() throws IOException {
String ret = null;
try {
byte[] decodedPassword = Base64.decode(password);
- Cipher engine = Cipher.getInstance(CRYPT_ALGO);
+ Cipher engine = Cipher.getInstance(cryptAlgo);
PBEKeySpec keySpec = new PBEKeySpec(encryptKey);
- SecretKeyFactory skf = SecretKeyFactory.getInstance(CRYPT_ALGO);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(cryptAlgo);
SecretKey key = skf.generateSecret(keySpec);
- engine.init(Cipher.DECRYPT_MODE, key,new PBEParameterSpec(salt,
ITERATION_COUNT));
+ engine.init(Cipher.DECRYPT_MODE, key,new PBEParameterSpec(salt,
iterationCount, new IvParameterSpec(iv)));
String decrypted = new String(engine.doFinal(decodedPassword));
int foundAt = decrypted.indexOf(LEN_SEPARATOR_STR);
if (foundAt > -1) {
@@ -150,6 +168,53 @@ public class PasswordUtils {
return ret;
}
+ public static boolean needsIv(String cryptoAlgo) {
+ if (Strings.isNullOrEmpty(cryptoAlgo))
+ return false;
+
+ return
PBE_SHA512_AES_128.toLowerCase().equals(cryptoAlgo.toLowerCase())
+ || cryptoAlgo.toLowerCase().contains("aes_128")
|| cryptoAlgo.toLowerCase().contains("aes_256");
+ }
+
+ public static String generateIvIfNeeded(String cryptAlgo) throws
NoSuchAlgorithmException {
+ if (!needsIv(cryptAlgo))
+ return null;
+ return generateBase64EncodedIV();
+ }
+
+ private static String generateBase64EncodedIV() throws
NoSuchAlgorithmException {
+ byte[] iv = new byte[16];
+ SecureRandom.getInstanceStrong().nextBytes(iv);
+ return new String(Base64.encode(iv));
+ }
+
+ public String getCryptAlgo() {
+ return cryptAlgo;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public int getIterationCount() {
+ return iterationCount;
+ }
+
+ public char[] getEncryptKey() {
+ return encryptKey;
+ }
+
+ public byte[] getSalt() {
+ return salt;
+ }
+
+ public byte[] getIv() {
+ return iv;
+ }
+
+ public String getIvAsString() {
+ return new String(Base64.encode(getIv()));
+ }
public static String getDecryptPassword(String password) {
String decryptedPwd = null;
try {
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/util/PasswordUtilsTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/util/PasswordUtilsTest.java
index 4e135aa..d0b1806 100644
---
a/agents-common/src/test/java/org/apache/ranger/plugin/util/PasswordUtilsTest.java
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/util/PasswordUtilsTest.java
@@ -22,46 +22,173 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
import org.junit.Test;
+import com.google.common.base.Joiner;
+
public class PasswordUtilsTest {
- @Test
- public void testEncrypt() throws IOException {
- String string0 =
PasswordUtils.encryptPassword("secretPasswordNoOneWillEverKnow");
- assertNotNull(string0);
-
assertEquals("ljoJ3gf4T018Xr+BujPAqBDW8Onp1PqprsLKmxus8pGGBETtAVU6OQ==",
string0);
- }
-
- @Test
- public void testDecrypt() throws IOException {
- String string0 =
PasswordUtils.decryptPassword("ljoJ3gf4T018Xr+BujPAqBDW8Onp1PqprsLKmxus8pGGBETtAVU6OQ==");
- assertNotNull(string0);
- assertEquals("secretPasswordNoOneWillEverKnow", string0);
- }
-
- @Test
- public void testEncryptWithExplicitDefaultWeakAlgorithm() throws
IOException {
- String string0 = PasswordUtils
-
.encryptPassword("PBEWithMD5AndDES,ENCRYPT_KEY,SALTSALT,4,secretPasswordNoOneWillEverKnow");
- assertNotNull(string0);
- String string1 =
PasswordUtils.decryptPassword("PBEWithMD5AndDES,ENCRYPT_KEY,SALTSALT,4," +
string0);
- assertNotNull("secretPasswordNoOneWillEverKnow", string1);
- }
-
- @Test
- public void testEncryptWithSHA1AndDESede() throws IOException {
- String string0 = PasswordUtils
-
.encryptPassword("PBEWithSHA1AndDESede,ENCRYPT_KEY,SALTSALT,4,secretPasswordNoOneWillEverKnow");
- assertNotNull(string0);
- String string1 =
PasswordUtils.decryptPassword("PBEWithSHA1AndDESede,ENCRYPT_KEY,SALTSALT,4," +
string0);
- assertNotNull("secretPasswordNoOneWillEverKnow", string1);
- }
-
- @Test
- public void testDecryptEmptyResultInNull() throws Throwable {
- String string0 = PasswordUtils.decryptPassword("");
- assertNull(string0);
- }
+ @Test
+ public void testEncrypt() throws IOException {
+ // encryption of password that contains no configuration info
is using legacy
+ // cryptography algorithm for backward compatibility.
+ String encryptedPassword =
PasswordUtils.encryptPassword("secretPasswordNoOneWillEverKnow");
+ assertNotNull(encryptedPassword);
+
assertEquals("ljoJ3gf4T018Xr+BujPAqBDW8Onp1PqprsLKmxus8pGGBETtAVU6OQ==",
encryptedPassword);
+ }
+
+ @Test
+ public void testDecrypt() throws IOException {
+ String decryptedPassword = PasswordUtils
+
.decryptPassword("ljoJ3gf4T018Xr+BujPAqBDW8Onp1PqprsLKmxus8pGGBETtAVU6OQ==");
+
+ assertNotNull(decryptedPassword);
+ assertEquals("secretPasswordNoOneWillEverKnow",
decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithExplicitDefaultWeakAlgorithm() throws
IOException {
+ String freeTextPasswordMetaData = join("PBEWithMD5AndDES",
"ENCRYPT_KEY", "SALTSALT", "4");
+ String encryptedPassword = PasswordUtils
+ .encryptPassword(join(freeTextPasswordMetaData,
"secretPasswordNoOneWillEverKnow"));
+ assertNotNull(encryptedPassword);
+
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals("secretPasswordNoOneWillEverKnow",
decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA1AndDESede() throws IOException {
+ String freeTextPasswordMetaData = join("PBEWithSHA1AndDESede",
"ENCRYPT_KEY", "SALTSALT", "4");
+ String encryptedPassword = PasswordUtils
+ .encryptPassword(join(freeTextPasswordMetaData,
"secretPasswordNoOneWillEverKnow"));
+ assertNotNull(encryptedPassword);
+
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals("secretPasswordNoOneWillEverKnow",
decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128() throws IOException,
NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
join("PBEWITHHMACSHA512ANDAES_128", "ENCRYPT_KEY", "SALTSALT", "4",
+
PasswordUtils.generateIvIfNeeded("PBEWITHHMACSHA512ANDAES_128"));
+ String encryptedPassword = PasswordUtils
+ .encryptPassword(join(freeTextPasswordMetaData,
"secretPasswordNoOneWillEverKnow"));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals("secretPasswordNoOneWillEverKnow",
decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128WithMultipleComasInPass()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = "asd,qwe,123";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128WithSingleComaInPass() throws
IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = "asd,123";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128EndingWithSingleComa() throws
IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = "asd,";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128StartingWithSingleComa()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = ",asd";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128MultipleComasInTheEnd()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = "asd,,";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128MultipleComasSurroundingText()
+ throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = ",,a,,";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128MultipleComasBeforeText()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = ",,,a";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128MultipleComasOnlyPassword()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = ",,,";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testEncryptWithSHA512AndAES128SingleComaOnlyPassword()
throws IOException, NoSuchAlgorithmException {
+ String freeTextPasswordMetaData =
"PBEWITHHMACSHA512ANDAES_128,tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV,f77aLYLo,1000,9f3vNL0ijeHF4RWN/yUo0A==";
+ String freeTextPassword = ",";
+ String encryptedPassword =
PasswordUtils.encryptPassword(join(freeTextPasswordMetaData, freeTextPassword));
+
+ assertNotNull(encryptedPassword);
+ String decryptedPassword =
PasswordUtils.decryptPassword(join(freeTextPasswordMetaData,
encryptedPassword));
+ assertEquals(freeTextPassword, decryptedPassword);
+ }
+
+ @Test
+ public void testDecryptEmptyResultInNull() throws Throwable {
+ String string0 = PasswordUtils.decryptPassword("");
+ assertNull(string0);
+ }
+
+ private String join(String... strings) {
+ return Joiner.on(",").skipNulls().join(strings);
+ }
}
diff --git
a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 0e0e485..77c91ab 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -175,6 +175,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
+import com.google.common.base.Joiner;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -1451,12 +1452,17 @@ public class ServiceDBStore extends
AbstractServiceStore {
}
if (StringUtils.equalsIgnoreCase(configKey,
CONFIG_KEY_PASSWORD)) {
- String cryptConfigString = CRYPT_ALGO + "," +
ENCRYPT_KEY + "," + SALT + "," + ITERATION_COUNT + "," + configValue;
- String encryptedPwd =
PasswordUtils.encryptPassword(cryptConfigString);
- encryptedPwd = CRYPT_ALGO + "," + ENCRYPT_KEY
+ "," + SALT + "," + ITERATION_COUNT + "," + encryptedPwd;
- String decryptedPwd =
PasswordUtils.decryptPassword(encryptedPwd);
+ Joiner joiner = Joiner.on(",").skipNulls();
+ String iv =
PasswordUtils.generateIvIfNeeded(CRYPT_ALGO);
+
+ String cryptConfigString =
joiner.join(CRYPT_ALGO, ENCRYPT_KEY, SALT, ITERATION_COUNT, iv, configValue);
+ String encryptedPwd =
PasswordUtils.encryptPassword(cryptConfigString);
+
+ String paddedEncryptedPwd =
joiner.join(CRYPT_ALGO, ENCRYPT_KEY, SALT, ITERATION_COUNT, iv,
+ encryptedPwd);
+ String decryptedPwd =
PasswordUtils.decryptPassword(paddedEncryptedPwd);
if (StringUtils.equals(decryptedPwd,
configValue)) {
- configValue = encryptedPwd;
+ configValue = paddedEncryptedPwd;
}
}
@@ -1633,42 +1639,31 @@ public class ServiceDBStore extends
AbstractServiceStore {
if (StringUtils.equalsIgnoreCase(configKey,
CONFIG_KEY_PASSWORD)) {
if (StringUtils.equalsIgnoreCase(configValue,
HIDDEN_PASSWORD_STR)) {
- String[] crypt_algo_array = null;
- if (configValue.contains(",")) {
- crypt_algo_array =
configValue.split(",");
- }
- if (oldPassword != null &&
oldPassword.contains(",")) {
- String encryptKey = null;
- String salt = null;
- int iterationCount = 0;
-
- crypt_algo_array =
oldPassword.split(",");
- String OLD_CRYPT_ALGO =
crypt_algo_array[0];
- encryptKey =
crypt_algo_array[1];
- salt = crypt_algo_array[2];
- iterationCount =
Integer.parseInt(crypt_algo_array[3]);
-
- if
(!OLD_CRYPT_ALGO.equalsIgnoreCase(CRYPT_ALGO)) {
- String decryptedPwd =
PasswordUtils.decryptPassword(oldPassword);
- String paddingString =
CRYPT_ALGO + "," + encryptKey + "," + salt + "," + iterationCount;
- String encryptedPwd =
PasswordUtils.encryptPassword(paddingString + "," + decryptedPwd);
- String newDecryptedPwd
= PasswordUtils.decryptPassword(paddingString + "," + encryptedPwd);
- if
(StringUtils.equals(newDecryptedPwd, decryptedPwd)) {
- configValue =
paddingString + "," + encryptedPwd;
- }
- } else {
- configValue =
oldPassword;
- }
- } else {
- configValue = oldPassword;
- }
+ if (oldPassword != null &&
oldPassword.contains(",")) {
+ PasswordUtils util =
PasswordUtils.build(oldPassword);
+ if
(!util.getCryptAlgo().equalsIgnoreCase(CRYPT_ALGO)) {
+ String decryptedPwd =
PasswordUtils.decryptPassword(oldPassword);
+ String paddingString =
Joiner.on(",").skipNulls().join(CRYPT_ALGO,
+ new
String(util.getEncryptKey()), new String(util.getSalt()),
+
util.getIterationCount(), PasswordUtils.generateIvIfNeeded(CRYPT_ALGO));
+ String encryptedPwd =
PasswordUtils.encryptPassword(paddingString + "," + decryptedPwd);
+ String newDecryptedPwd
= PasswordUtils.decryptPassword(paddingString + "," + encryptedPwd);
+ if
(StringUtils.equals(newDecryptedPwd, decryptedPwd)) {
+ configValue =
paddingString + "," + encryptedPwd;
+ }
+ } else {
+ configValue =
oldPassword;
+ }
+ } else {
+
configValue = oldPassword;
+
}
} else {
- String paddingString = CRYPT_ALGO +
"," + ENCRYPT_KEY + "," + SALT + "," + ITERATION_COUNT;
- String encryptedPwd =
PasswordUtils.encryptPassword(paddingString + "," +configValue);
- String decryptedPwd =
PasswordUtils.decryptPassword(paddingString + "," +encryptedPwd);
-
+ String paddingString =
Joiner.on(",").skipNulls().join(CRYPT_ALGO, ENCRYPT_KEY, SALT,
+ ITERATION_COUNT,
PasswordUtils.generateIvIfNeeded(CRYPT_ALGO));
+ String encryptedPwd =
PasswordUtils.encryptPassword(paddingString + "," + configValue);
+ String decryptedPwd =
PasswordUtils.decryptPassword(paddingString + "," + encryptedPwd);
if (StringUtils.equals(decryptedPwd,
configValue)) {
- configValue = paddingString +
"," + encryptedPwd;
+ configValue = paddingString +
"," + encryptedPwd;
}
}
}
diff --git
a/security-admin/src/main/java/org/apache/ranger/patch/cliutil/ChangePasswordUtil.java
b/security-admin/src/main/java/org/apache/ranger/patch/cliutil/ChangePasswordUtil.java
index 3037053..65b9ccb 100644
---
a/security-admin/src/main/java/org/apache/ranger/patch/cliutil/ChangePasswordUtil.java
+++
b/security-admin/src/main/java/org/apache/ranger/patch/cliutil/ChangePasswordUtil.java
@@ -189,7 +189,6 @@ public class ChangePasswordUtil extends BaseLoader {
currentEncryptedPassword =
userMgr.encrypt(userLoginIdTemp, currentPasswordTemp);
if
(currentEncryptedPassword.equals(dbPassword)) {
validatePassword(newPasswordTemp);
- logger.info("User:" +
userLoginIdTemp + "|Password:"+newPasswordTemp);
userMgr.updatePasswordInSHA256(userLoginIdTemp, newPasswordTemp, true);
logger.info("User '" +
userLoginIdTemp + "' Password updated sucessfully.");
} else if
(!currentEncryptedPassword.equals(dbPassword) && defaultPwdChangeRequest) {
diff --git
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
index 2ddb5f3..6344209 100644
---
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
+++
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
@@ -17,7 +17,6 @@
package org.apache.ranger.service;
-import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
@@ -46,6 +45,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
+import com.google.common.base.Joiner;
+
@Service
@Scope("singleton")
public class RangerServiceService extends RangerServiceServiceBase<XXService,
RangerService> {
@@ -290,42 +291,41 @@ public class RangerServiceService extends
RangerServiceServiceBase<XXService, Ra
return xTrxLog;
}
- public Map<String, String>
getConfigsWithDecryptedPassword(RangerService service) throws IOException {
+ public Map<String, String>
getConfigsWithDecryptedPassword(RangerService service) throws Exception {
Map<String, String> configs = service.getConfigs();
String pwd = configs.get(ServiceDBStore.CONFIG_KEY_PASSWORD);
if(!stringUtil.isEmpty(pwd) &&
ServiceDBStore.HIDDEN_PASSWORD_STR.equalsIgnoreCase(pwd)) {
XXServiceConfigMap pwdConfig =
daoMgr.getXXServiceConfigMap().findByServiceAndConfigKey(service.getId(),
ServiceDBStore.CONFIG_KEY_PASSWORD);
- if (pwdConfig != null) {
+
+ if (pwdConfig != null) {
String encryptedPwd =
pwdConfig.getConfigvalue();
- String decryptedPwd = "";
- String crypt_algo_array[] = null;
- if (encryptedPwd.contains(",")) {
- crypt_algo_array =
encryptedPwd.split(",");
- }
- if (crypt_algo_array != null &&
crypt_algo_array.length > 1) {
- String cryptAlgo = null;
- String encryptKey = null;
- String salt = null;
- int iterationCount = 0;
- cryptAlgo = crypt_algo_array[0];
- encryptKey = crypt_algo_array[1];
- salt = crypt_algo_array[2];
- iterationCount =
Integer.parseInt(crypt_algo_array[3]);
-
- String paddingString = cryptAlgo + ","
+ encryptKey + "," + salt + "," + iterationCount;
- decryptedPwd =
PasswordUtils.decryptPassword(encryptedPwd);
-
- if
(StringUtils.equalsIgnoreCase(paddingString + "," +
PasswordUtils.encryptPassword(paddingString + "," + decryptedPwd),
encryptedPwd)) {
-
configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd);
- }
- } else {
- encryptedPwd =
pwdConfig.getConfigvalue();
- decryptedPwd =
PasswordUtils.decryptPassword(encryptedPwd);
- if
(StringUtils.equalsIgnoreCase(PasswordUtils.encryptPassword(decryptedPwd),
encryptedPwd)) {
-
configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd);
- }
+ if (encryptedPwd.contains(",")) {
+ PasswordUtils util =
PasswordUtils.build(encryptedPwd);
+ String freeTextPasswordMetaData =
Joiner.on(",").skipNulls().join(util.getCryptAlgo(),
+ new
String(util.getEncryptKey()), new String(util.getSalt()),
util.getIterationCount(),
+
PasswordUtils.needsIv(util.getCryptAlgo()) ? util.getIvAsString() : null);
+ String decryptedPwd =
PasswordUtils.decryptPassword(encryptedPwd);
+ if (StringUtils
+ .equalsIgnoreCase(
+
freeTextPasswordMetaData + ","
+
+ PasswordUtils
+
.encryptPassword(freeTextPasswordMetaData + "," +
decryptedPwd),
+
encryptedPwd)) {
+
configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd); // XXX: method
name is
+
// getConfigsWithDecryptedPassword,
+
// then why do we store the
+
// encryptedPwd?
+ }
+ } else {
+ String decryptedPwd =
PasswordUtils.decryptPassword(encryptedPwd);
+ if
(StringUtils.equalsIgnoreCase(PasswordUtils.encryptPassword(decryptedPwd),
encryptedPwd)) {
+
configs.put(ServiceDBStore.CONFIG_KEY_PASSWORD, encryptedPwd); // XXX: method
name is
+
// getConfigsWithDecryptedPassword,
+
// then why do we store the
+
// encryptedPwd?
+ }
}
}
}
diff --git
a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
index 8ebeeb5..eb7947a 100644
--- a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
+++ b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
@@ -568,7 +568,7 @@
</property>
<property>
<name>ranger.password.encryption.algorithm</name>
- <value>PBEWithMD5AndDES</value>
+ <value>PBEWithHmacSHA512AndAES_128</value>
</property>
<property>
<name>ranger.default.browser-useragents</name>
diff --git
a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
index f0a6079..b6f13f4 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
@@ -2215,6 +2215,89 @@ public class TestServiceDBStore {
Mockito.verify(daoManager).getXXPolicy();
}
+ @Test
+ public void test41updateServiceCryptAlgo() throws Exception {
+ XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
+ XXService xService = Mockito.mock(XXService.class);
+ XXServiceConfigMapDao xServiceConfigMapDao = Mockito
+ .mock(XXServiceConfigMapDao.class);
+ XXServiceConfigDefDao xServiceConfigDefDao = Mockito
+ .mock(XXServiceConfigDefDao.class);
+ XXUserDao xUserDao = Mockito.mock(XXUserDao.class);
+
+ RangerService rangerService = rangerService();
+
rangerService.getConfigs().put(ServiceDBStore.CONFIG_KEY_PASSWORD, "*****");
+
+ Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
+ Mockito.when(xServiceDao.getById(Id)).thenReturn(xService);
+
+ Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
+
+ List<XXServiceConfigDef> xServiceConfigDefList = new
ArrayList<XXServiceConfigDef>();
+ XXServiceConfigDef serviceConfigDefObj = new
XXServiceConfigDef();
+ serviceConfigDefObj.setId(Id);
+ xServiceConfigDefList.add(serviceConfigDefObj);
+ Mockito.when(daoManager.getXXServiceConfigDef()).thenReturn(
+ xServiceConfigDefDao);
+
+ Mockito.when(svcService.update(rangerService))
+ .thenReturn(rangerService);
+ Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
+ Mockito.when(xServiceDao.getById(Id)).thenReturn(xService);
+
+ // the old pass
+ List<XXServiceConfigMap> xConfMapList = new
ArrayList<XXServiceConfigMap>();
+ XXServiceConfigMap xConfMap = new XXServiceConfigMap();
+ xConfMap.setAddedByUserId(null);
+ xConfMap.setConfigkey(ServiceDBStore.CONFIG_KEY_PASSWORD);
+ //old outdated
+
xConfMap.setConfigvalue("PBEWithSHA1AndDESede,ENCRYPT_KEY,SALTSALT,4,lXintlvY73rdk3jXvD7CqB5mcSKl0AMhouBbI5m3whrhLdbKddnzxA==");
+ xConfMap.setCreateTime(new Date());
+ xConfMap.setServiceId(null);
+ xConfMap.setUpdatedByUserId(null);
+ xConfMap.setUpdateTime(new Date());
+ xConfMapList.add(xConfMap);
+
+ Mockito.when(daoManager.getXXServiceConfigMap()).thenReturn(
+ xServiceConfigMapDao);
+ Mockito.when(xServiceConfigMapDao.findByServiceId(Id)).thenReturn(
+ xConfMapList);
+ Mockito.when(daoManager.getXXServiceConfigMap()).thenReturn(
+ xServiceConfigMapDao);
+ Mockito.when(xServiceConfigMapDao.remove(xConfMap)).thenReturn(true);
+
+ Mockito.when(daoManager.getXXServiceConfigMap()).thenReturn(
+ xServiceConfigMapDao);
+ Mockito.when(daoManager.getXXUser()).thenReturn(xUserDao);
+
+ Mockito.when(
+ rangerAuditFields.populateAuditFields(
+ Mockito.isA(XXServiceConfigMap.class),
+
Mockito.isA(XXService.class))).thenReturn(xConfMap);
+
+ Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
+ rangerService);
+
+ XXServiceResourceDao xServiceResourceDao =
Mockito.mock(XXServiceResourceDao.class);
+
Mockito.when(daoManager.getXXServiceResource()).thenReturn(xServiceResourceDao);
+
Mockito.when(xServiceResourceDao.countTaggedResourcesInServiceId(xService.getId())).thenReturn(0L);
+ Map<String, Object> options = null;
+ RangerService dbRangerService = serviceDBStore
+ .updateService(rangerService, options);
+
+ Assert.assertNotNull(dbRangerService);
+ Assert.assertEquals(dbRangerService, rangerService);
+ Assert.assertEquals(dbRangerService.getId(), rangerService.getId());
+ Assert.assertEquals(dbRangerService.getName(), rangerService.getName());
+ Assert.assertEquals(dbRangerService.getCreatedBy(),
+ rangerService.getCreatedBy());
+ Assert.assertEquals(dbRangerService.getDescription(),
+ rangerService.getDescription());
+ Assert.assertEquals(dbRangerService.getType(), rangerService.getType());
+ Assert.assertEquals(dbRangerService.getVersion(),
+ rangerService.getVersion());
+ Mockito.verify(daoManager).getXXUser();
+}
@Test
public void test41getMetricByTypeusergroup() throws Exception{
VXGroupList vxGroupList = new VXGroupList();