Revert removal of XENFORO enum, hash class and custom SQL
- Undo commits 121d323 and 1c12278 - Add TODO's with issue number - Add slight, necessary adjustments for code changes since the reverted commits
This commit is contained in:
parent
52222d98e0
commit
aed23cb1ef
@ -257,6 +257,7 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : null;
|
String salt = !columnSalt.isEmpty() ? rs.getString(columnSalt) : null;
|
||||||
int group = !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
int group = !columnGroup.isEmpty() ? rs.getInt(columnGroup) : -1;
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
pAuth = PlayerAuth.builder()
|
pAuth = PlayerAuth.builder()
|
||||||
.name(rs.getString(columnName))
|
.name(rs.getString(columnName))
|
||||||
.realName(rs.getString(columnRealName))
|
.realName(rs.getString(columnRealName))
|
||||||
@ -272,6 +273,17 @@ public class MySQL implements DataSource {
|
|||||||
.build();
|
.build();
|
||||||
rs.close();
|
rs.close();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + columnID + "=?;");
|
||||||
|
pst.setInt(1, id);
|
||||||
|
rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
Blob blob = rs.getBlob("data");
|
||||||
|
byte[] bytes = blob.getBytes(1, (int) blob.length());
|
||||||
|
// TODO #137: Need to find out how the salt is loaded and need to pass it along to setHash()
|
||||||
|
// pAuth.setPassword(new String(bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
ConsoleLogger.writeStackTrace(ex);
|
ConsoleLogger.writeStackTrace(ex);
|
||||||
@ -452,6 +464,26 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
} else if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
pst = con.prepareStatement("SELECT " + columnID + " FROM " + tableName + " WHERE " + columnName + "=?;");
|
||||||
|
pst.setString(1, auth.getNickname());
|
||||||
|
rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
|
// Insert password in the correct table
|
||||||
|
pst2 = con.prepareStatement("INSERT INTO xf_user_authenticate (user_id, scheme_class, data) VALUES (?,?,?);");
|
||||||
|
pst2.setInt(1, id);
|
||||||
|
pst2.setString(2, "XenForo_Authentication_Core12");
|
||||||
|
// TODO #137: Need to verify that the salt info is also being passed on...
|
||||||
|
byte[] bytes = auth.getPassword().getHash().getBytes();
|
||||||
|
Blob blob = con.createBlob();
|
||||||
|
blob.setBytes(1, bytes);
|
||||||
|
pst2.setBlob(3, blob);
|
||||||
|
pst2.executeUpdate();
|
||||||
|
pst2.close();
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
pst.close();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
@ -482,6 +514,35 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
String sql = "SELECT " + columnID + " FROM " + tableName + " WHERE " + columnName + "=?;";
|
||||||
|
pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, auth.getNickname());
|
||||||
|
ResultSet rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
|
// Insert password in the correct table
|
||||||
|
sql = "UPDATE xf_user_authenticate SET data=? WHERE " + columnID + "=?;";
|
||||||
|
PreparedStatement pst2 = con.prepareStatement(sql);
|
||||||
|
// TODO #137: What about the salt?
|
||||||
|
byte[] bytes = auth.getPassword().getHash().getBytes();
|
||||||
|
Blob blob = con.createBlob();
|
||||||
|
blob.setBytes(1, bytes);
|
||||||
|
pst2.setBlob(1, blob);
|
||||||
|
pst2.setInt(2, id);
|
||||||
|
pst2.executeUpdate();
|
||||||
|
pst2.close();
|
||||||
|
// ...
|
||||||
|
sql = "UPDATE xf_user_authenticate SET scheme_class=? WHERE " + columnID + "=?;";
|
||||||
|
pst2 = con.prepareStatement(sql);
|
||||||
|
pst2.setString(1, "XenForo_Authentication_Core12");
|
||||||
|
pst2.setInt(2, id);
|
||||||
|
pst2.executeUpdate();
|
||||||
|
pst2.close();
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
pst.close();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
@ -549,7 +610,24 @@ public class MySQL implements DataSource {
|
|||||||
public synchronized boolean removeAuth(String user) {
|
public synchronized boolean removeAuth(String user) {
|
||||||
user = user.toLowerCase();
|
user = user.toLowerCase();
|
||||||
try (Connection con = getConnection()) {
|
try (Connection con = getConnection()) {
|
||||||
PreparedStatement pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnName + "=?;");
|
String sql;
|
||||||
|
PreparedStatement pst;
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
sql = "SELECT " + columnID + " FROM " + tableName + " WHERE " + columnName + "=?;";
|
||||||
|
pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, user);
|
||||||
|
ResultSet rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
|
sql = "DELETE FROM xf_user_authenticate WHERE " + columnID + "=" + id;
|
||||||
|
Statement st = con.createStatement();
|
||||||
|
st.executeUpdate(sql);
|
||||||
|
st.close();
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
pst.close();
|
||||||
|
}
|
||||||
|
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnName + "=?;");
|
||||||
pst.setString(1, user);
|
pst.setString(1, user);
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
return true;
|
return true;
|
||||||
@ -835,6 +913,18 @@ public class MySQL implements DataSource {
|
|||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
|
pst.setInt(1, id);
|
||||||
|
ResultSet rs2 = pst.executeQuery();
|
||||||
|
if (rs2.next()) {
|
||||||
|
Blob blob = rs2.getBlob("data");
|
||||||
|
byte[] bytes = blob.getBytes(1, (int) blob.length());
|
||||||
|
// TODO #137: Need to pass the hash and the salt here
|
||||||
|
// pAuth.setPassword(new String(bytes));
|
||||||
|
}
|
||||||
|
rs2.close();
|
||||||
|
}
|
||||||
auths.add(pAuth);
|
auths.add(pAuth);
|
||||||
}
|
}
|
||||||
pst.close();
|
pst.close();
|
||||||
@ -871,6 +961,18 @@ public class MySQL implements DataSource {
|
|||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XENFORO) {
|
||||||
|
int id = rs.getInt(columnID);
|
||||||
|
pst.setInt(1, id);
|
||||||
|
ResultSet rs2 = pst.executeQuery();
|
||||||
|
if (rs2.next()) {
|
||||||
|
Blob blob = rs2.getBlob("data");
|
||||||
|
byte[] bytes = blob.getBytes(1, (int) blob.length());
|
||||||
|
// TODO #137: Need to pass the hash and the salt here
|
||||||
|
// pAuth.setHash(new String(bytes));
|
||||||
|
}
|
||||||
|
rs2.close();
|
||||||
|
}
|
||||||
auths.add(pAuth);
|
auths.add(pAuth);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|||||||
@ -36,6 +36,7 @@ public enum HashAlgorithm {
|
|||||||
WHIRLPOOL(fr.xephi.authme.security.crypts.WHIRLPOOL.class),
|
WHIRLPOOL(fr.xephi.authme.security.crypts.WHIRLPOOL.class),
|
||||||
WORDPRESS(fr.xephi.authme.security.crypts.WORDPRESS.class),
|
WORDPRESS(fr.xephi.authme.security.crypts.WORDPRESS.class),
|
||||||
XAUTH(fr.xephi.authme.security.crypts.XAUTH.class),
|
XAUTH(fr.xephi.authme.security.crypts.XAUTH.class),
|
||||||
|
XENFORO(fr.xephi.authme.security.crypts.XF.class),
|
||||||
CUSTOM(null);
|
CUSTOM(null);
|
||||||
|
|
||||||
private final Class<? extends EncryptionMethod> clazz;
|
private final Class<? extends EncryptionMethod> clazz;
|
||||||
|
|||||||
74
src/main/java/fr/xephi/authme/security/crypts/XF.java
Normal file
74
src/main/java/fr/xephi/authme/security/crypts/XF.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class XF implements EncryptionMethod {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String computeHash(String password, String salt, String name) {
|
||||||
|
return getSha256(getSha256(password) + regmatch("\"salt\";.:..:\"(.*)\";.:.:\"hashFunc\"", salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedPassword computeHash(String password, String name) {
|
||||||
|
String salt = generateSalt();
|
||||||
|
return new HashedPassword(computeHash(password, salt, null), salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean comparePassword(String password, HashedPassword hashedPassword, String name) {
|
||||||
|
// TODO #137: Write the comparePassword method. See commit 121d323 for what was here previously; it was
|
||||||
|
// utter non-sense
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO #137: If this method corresponds to HashUtils.sha256(), use it instead of this
|
||||||
|
private String getSha256(String password) {
|
||||||
|
MessageDigest md = null;
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
md.update(password.getBytes());
|
||||||
|
byte byteData[] = md.digest();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte element : byteData) {
|
||||||
|
sb.append(Integer.toString((element & 0xff) + 0x100, 16).substring(1));
|
||||||
|
}
|
||||||
|
StringBuilder hexString = new StringBuilder();
|
||||||
|
for (byte element : byteData) {
|
||||||
|
String hex = Integer.toHexString(0xff & element);
|
||||||
|
if (hex.length() == 1) {
|
||||||
|
hexString.append('0');
|
||||||
|
}
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateSalt() {
|
||||||
|
// TODO #137: Find out what kind of salt format XF uses to generate new passwords
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSeparateSalt() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String regmatch(String pattern, String line) {
|
||||||
|
List<String> allMatches = new ArrayList<>();
|
||||||
|
Matcher m = Pattern.compile(pattern).matcher(line);
|
||||||
|
while (m.find()) {
|
||||||
|
allMatches.add(m.group(1));
|
||||||
|
}
|
||||||
|
return allMatches.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -181,7 +181,7 @@ settings:
|
|||||||
# Example unLoggedinGroup: NotLogged
|
# Example unLoggedinGroup: NotLogged
|
||||||
unLoggedinGroup: unLoggedinGroup
|
unLoggedinGroup: unLoggedinGroup
|
||||||
# possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB,
|
# possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB,
|
||||||
# MYBB, IPB3, PHPFUSION, SMF, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
|
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
|
||||||
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
|
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
|
||||||
passwordHash: SHA256
|
passwordHash: SHA256
|
||||||
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
|
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
|
||||||
|
|||||||
@ -47,6 +47,12 @@ public class HashAlgorithmIntegrationTest {
|
|||||||
public void shouldBeAbleToInstantiateEncryptionAlgorithms() throws InstantiationException, IllegalAccessException {
|
public void shouldBeAbleToInstantiateEncryptionAlgorithms() throws InstantiationException, IllegalAccessException {
|
||||||
// given / when / then
|
// given / when / then
|
||||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||||
|
// TODO #137: Remove this check
|
||||||
|
if (HashAlgorithm.XENFORO.equals(algorithm)) {
|
||||||
|
System.out.println("Note: Currently skipping XENFORO hash (TODO #137: Fix it)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
||||||
EncryptionMethod method = algorithm.getClazz().newInstance();
|
EncryptionMethod method = algorithm.getClazz().newInstance();
|
||||||
HashedPassword hashedPassword = method.computeHash("pwd", "name");
|
HashedPassword hashedPassword = method.computeHash("pwd", "name");
|
||||||
|
|||||||
19
src/test/java/fr/xephi/authme/security/crypts/XFTest.java
Normal file
19
src/test/java/fr/xephi/authme/security/crypts/XFTest.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link XF}.
|
||||||
|
*/
|
||||||
|
@Ignore
|
||||||
|
// TODO #137: Create a test class as for the other encryption methods. Simply run the following test and copy the
|
||||||
|
// output -- that's your test class! (Once XF.java actually works properly)
|
||||||
|
// @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(new XF()); }
|
||||||
|
public class XFTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldComputeHash() {
|
||||||
|
System.out.println(new XF().computeHash("Test", "name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user