mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-23 17:17:36 +01:00
Merge branch 'master' of https://github.com/AuthMe-Team/AuthMeReloaded.git
This commit is contained in:
commit
b8ae8d995b
@ -10,6 +10,7 @@ import com.google.common.cache.RemovalNotification;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -57,6 +58,25 @@ public class CacheDataSource implements DataSource {
|
|||||||
return getAuth(user) != null;
|
return getAuth(user) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedPassword getPassword(String user) {
|
||||||
|
user = user.toLowerCase();
|
||||||
|
Optional<PlayerAuth> pAuthOpt = cachedAuths.getIfPresent(user);
|
||||||
|
if (pAuthOpt != null && pAuthOpt.isPresent()) {
|
||||||
|
return pAuthOpt.get().getPassword();
|
||||||
|
}
|
||||||
|
return source.getPassword(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method getAuth.
|
||||||
|
*
|
||||||
|
* @param user String
|
||||||
|
*
|
||||||
|
* @return PlayerAuth
|
||||||
|
*
|
||||||
|
* @see fr.xephi.authme.datasource.DataSource#getAuth(String)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized PlayerAuth getAuth(String user) {
|
public synchronized PlayerAuth getAuth(String user) {
|
||||||
user = user.toLowerCase();
|
user = user.toLowerCase();
|
||||||
@ -81,6 +101,16 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
|
user = user.toLowerCase();
|
||||||
|
boolean result = source.updatePassword(user, password);
|
||||||
|
if (result) {
|
||||||
|
cachedAuths.refresh(user);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSession(PlayerAuth auth) {
|
public boolean updateSession(PlayerAuth auth) {
|
||||||
boolean result = source.updateSession(auth);
|
boolean result = source.updateSession(auth);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package fr.xephi.authme.datasource;
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@ -17,6 +18,15 @@ public interface DataSource {
|
|||||||
*/
|
*/
|
||||||
boolean isAuthAvailable(String user);
|
boolean isAuthAvailable(String user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method getPassword.
|
||||||
|
*
|
||||||
|
* @param user String
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
HashedPassword getPassword(String user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method getAuth.
|
* Method getAuth.
|
||||||
*
|
*
|
||||||
@ -53,6 +63,8 @@ public interface DataSource {
|
|||||||
*/
|
*/
|
||||||
boolean updatePassword(PlayerAuth auth);
|
boolean updatePassword(PlayerAuth auth);
|
||||||
|
|
||||||
|
boolean updatePassword(String user, HashedPassword password);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method purgeDatabase.
|
* Method purgeDatabase.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package fr.xephi.authme.datasource;
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -10,12 +17,6 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.cache.auth.PlayerCache;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -87,6 +88,15 @@ public class FlatFile implements DataSource {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedPassword getPassword(String user) {
|
||||||
|
PlayerAuth auth = getAuth(user);
|
||||||
|
if (auth != null) {
|
||||||
|
return auth.getPassword();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method saveAuth.
|
* Method saveAuth.
|
||||||
*
|
*
|
||||||
@ -126,7 +136,13 @@ public class FlatFile implements DataSource {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
if (!isAuthAvailable(auth.getNickname())) {
|
return updatePassword(auth.getNickname(), auth.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
|
user = user.toLowerCase();
|
||||||
|
if (!isAuthAvailable(user)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PlayerAuth newAuth = null;
|
PlayerAuth newAuth = null;
|
||||||
@ -136,27 +152,27 @@ public class FlatFile implements DataSource {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equals(auth.getNickname())) {
|
if (args[0].equals(user)) {
|
||||||
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 4: {
|
case 4: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 7: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 8: {
|
case 8: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 9: {
|
case 9: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
newAuth = new PlayerAuth(args[0], auth.getPassword().getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
|
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +194,7 @@ public class FlatFile implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newAuth != null) {
|
if (newAuth != null) {
|
||||||
removeAuth(auth.getNickname());
|
removeAuth(user);
|
||||||
saveAuth(newAuth);
|
saveAuth(newAuth);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -6,10 +6,18 @@ import fr.xephi.authme.AuthMe;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.security.crypts.XFBCRYPT;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.Blob;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -244,6 +252,25 @@ public class MySQL implements DataSource {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedPassword getPassword(String user) {
|
||||||
|
try (Connection con = getConnection()) {
|
||||||
|
String sql = "SELECT " + columnPassword + "," + columnSalt + " FROM " + tableName
|
||||||
|
+ " WHERE " + columnName + "=?;";
|
||||||
|
PreparedStatement pst = con.prepareStatement(sql);
|
||||||
|
pst.setString(1, user.toLowerCase());
|
||||||
|
ResultSet rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return new HashedPassword(rs.getString(columnPassword),
|
||||||
|
!columnSalt.isEmpty() ? rs.getString(columnSalt) : null);
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
ConsoleLogger.writeStackTrace(ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized PlayerAuth getAuth(String user) {
|
public synchronized PlayerAuth getAuth(String user) {
|
||||||
PlayerAuth pAuth;
|
PlayerAuth pAuth;
|
||||||
@ -257,6 +284,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 +300,16 @@ public class MySQL implements DataSource {
|
|||||||
.build();
|
.build();
|
||||||
rs.close();
|
rs.close();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XFBCRYPT) {
|
||||||
|
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());
|
||||||
|
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
ConsoleLogger.writeStackTrace(ex);
|
ConsoleLogger.writeStackTrace(ex);
|
||||||
@ -452,6 +490,24 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
} else if (Settings.getPasswordHash == HashAlgorithm.XFBCRYPT) {
|
||||||
|
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);
|
||||||
|
pst2 = con.prepareStatement("INSERT INTO xf_user_authenticate (user_id, scheme_class, data) VALUES (?,?,?);");
|
||||||
|
pst2.setInt(1, id);
|
||||||
|
pst2.setString(2, "XenForo_Authentication_Core12");
|
||||||
|
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) {
|
||||||
@ -463,6 +519,12 @@ public class MySQL implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
|
return updatePassword(auth.getNickname(), auth.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
|
user = user.toLowerCase();
|
||||||
try (Connection con = getConnection()) {
|
try (Connection con = getConnection()) {
|
||||||
boolean useSalt = !columnSalt.isEmpty();
|
boolean useSalt = !columnSalt.isEmpty();
|
||||||
PreparedStatement pst;
|
PreparedStatement pst;
|
||||||
@ -470,18 +532,46 @@ public class MySQL implements DataSource {
|
|||||||
String sql = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?;",
|
String sql = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?;",
|
||||||
tableName, columnPassword, columnSalt, columnName);
|
tableName, columnPassword, columnSalt, columnName);
|
||||||
pst = con.prepareStatement(sql);
|
pst = con.prepareStatement(sql);
|
||||||
pst.setString(1, auth.getPassword().getHash());
|
pst.setString(1, password.getHash());
|
||||||
pst.setString(2, auth.getPassword().getSalt());
|
pst.setString(2, password.getSalt());
|
||||||
pst.setString(3, auth.getNickname());
|
pst.setString(3, user);
|
||||||
} else {
|
} else {
|
||||||
String sql = String.format("UPDATE %s SET %s = ? WHERE %s = ?;",
|
String sql = String.format("UPDATE %s SET %s = ? WHERE %s = ?;",
|
||||||
tableName, columnPassword, columnName);
|
tableName, columnPassword, columnName);
|
||||||
pst = con.prepareStatement(sql);
|
pst = con.prepareStatement(sql);
|
||||||
pst.setString(1, auth.getPassword().getHash());
|
pst.setString(1, password.getHash());
|
||||||
pst.setString(2, auth.getNickname());
|
pst.setString(2, user);
|
||||||
}
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
pst.close();
|
pst.close();
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XFBCRYPT) {
|
||||||
|
String 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);
|
||||||
|
// Insert password in the correct table
|
||||||
|
sql = "UPDATE xf_user_authenticate SET data=? WHERE " + columnID + "=?;";
|
||||||
|
PreparedStatement pst2 = con.prepareStatement(sql);
|
||||||
|
byte[] bytes = password.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 +639,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.XFBCRYPT) {
|
||||||
|
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;
|
||||||
@ -679,7 +786,7 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<String> getAllAuthsByEmail(String email){
|
public synchronized List<String> getAllAuthsByEmail(String email) {
|
||||||
List<String> countEmail = new ArrayList<>();
|
List<String> countEmail = new ArrayList<>();
|
||||||
try (Connection con = getConnection()) {
|
try (Connection con = getConnection()) {
|
||||||
String sql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + columnEmail + "=?;";
|
String sql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + columnEmail + "=?;";
|
||||||
@ -835,6 +942,17 @@ public class MySQL implements DataSource {
|
|||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XFBCRYPT) {
|
||||||
|
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());
|
||||||
|
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
|
||||||
|
}
|
||||||
|
rs2.close();
|
||||||
|
}
|
||||||
auths.add(pAuth);
|
auths.add(pAuth);
|
||||||
}
|
}
|
||||||
pst.close();
|
pst.close();
|
||||||
@ -871,6 +989,17 @@ public class MySQL implements DataSource {
|
|||||||
.groupId(group)
|
.groupId(group)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
if (Settings.getPasswordHash == HashAlgorithm.XFBCRYPT) {
|
||||||
|
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());
|
||||||
|
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
|
||||||
|
}
|
||||||
|
rs2.close();
|
||||||
|
}
|
||||||
auths.add(pAuth);
|
auths.add(pAuth);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -156,6 +156,36 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedPassword getPassword(String user) {
|
||||||
|
PreparedStatement pst = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
pst = con.prepareStatement("SELECT " + columnPassword + "," + columnSalt
|
||||||
|
+ " FROM " + tableName + " WHERE " + columnName + "=?");
|
||||||
|
pst.setString(1, user);
|
||||||
|
rs = pst.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return new HashedPassword(rs.getString(columnPassword),
|
||||||
|
!columnSalt.isEmpty() ? rs.getString(columnSalt) : null);
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
ConsoleLogger.writeStackTrace(ex);
|
||||||
|
} finally {
|
||||||
|
close(rs);
|
||||||
|
close(pst);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method getAuth.
|
||||||
|
*
|
||||||
|
* @param user String
|
||||||
|
*
|
||||||
|
* @return PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getAuth(String)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized PlayerAuth getAuth(String user) {
|
public synchronized PlayerAuth getAuth(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -219,9 +249,14 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
|
return updatePassword(auth.getNickname(), auth.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
|
user = user.toLowerCase();
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
HashedPassword password = auth.getPassword();
|
|
||||||
boolean useSalt = !columnSalt.isEmpty();
|
boolean useSalt = !columnSalt.isEmpty();
|
||||||
String sql = "UPDATE " + tableName + " SET " + columnPassword + " = ?"
|
String sql = "UPDATE " + tableName + " SET " + columnPassword + " = ?"
|
||||||
+ (useSalt ? ", " + columnSalt + " = ?" : "")
|
+ (useSalt ? ", " + columnSalt + " = ?" : "")
|
||||||
@ -230,9 +265,9 @@ public class SQLite implements DataSource {
|
|||||||
pst.setString(1, password.getHash());
|
pst.setString(1, password.getHash());
|
||||||
if (useSalt) {
|
if (useSalt) {
|
||||||
pst.setString(2, password.getSalt());
|
pst.setString(2, password.getSalt());
|
||||||
pst.setString(3, auth.getNickname());
|
pst.setString(3, user);
|
||||||
} else {
|
} else {
|
||||||
pst.setString(2, auth.getNickname());
|
pst.setString(2, user);
|
||||||
}
|
}
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
|
@ -35,6 +35,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),
|
||||||
|
XFBCRYPT(fr.xephi.authme.security.crypts.XFBCRYPT.class),
|
||||||
CUSTOM(null);
|
CUSTOM(null);
|
||||||
|
|
||||||
private final Class<? extends EncryptionMethod> clazz;
|
private final Class<? extends EncryptionMethod> clazz;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package fr.xephi.authme.security;
|
package fr.xephi.authme.security;
|
||||||
|
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.events.PasswordEncryptionEvent;
|
import fr.xephi.authme.events.PasswordEncryptionEvent;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
|
||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,12 +35,8 @@ public class PasswordSecurity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean comparePassword(String password, String playerName) {
|
public boolean comparePassword(String password, String playerName) {
|
||||||
// TODO ljacqu 20151230: Defining a dataSource.getPassword() method would be more efficient
|
HashedPassword auth = dataSource.getPassword(playerName);
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
return auth != null && comparePassword(password, auth, playerName);
|
||||||
if (auth != null) {
|
|
||||||
return comparePassword(password, auth.getPassword(), playerName);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
|
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
|
||||||
@ -66,6 +61,7 @@ public class PasswordSecurity {
|
|||||||
* @param password The clear-text password to check
|
* @param password The clear-text password to check
|
||||||
* @param hashedPassword The encrypted password to test the clear-text password against
|
* @param hashedPassword The encrypted password to test the clear-text password against
|
||||||
* @param playerName The name of the player
|
* @param playerName The name of the player
|
||||||
|
*
|
||||||
* @return True if the
|
* @return True if the
|
||||||
*/
|
*/
|
||||||
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword,
|
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword,
|
||||||
@ -89,6 +85,7 @@ public class PasswordSecurity {
|
|||||||
*
|
*
|
||||||
* @param algorithm The algorithm to retrieve the encryption method for
|
* @param algorithm The algorithm to retrieve the encryption method for
|
||||||
* @param playerName The name of the player a password will be hashed for
|
* @param playerName The name of the player a password will be hashed for
|
||||||
|
*
|
||||||
* @return The encryption method
|
* @return The encryption method
|
||||||
*/
|
*/
|
||||||
private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm, String playerName) {
|
private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm, String playerName) {
|
||||||
@ -102,6 +99,7 @@ public class PasswordSecurity {
|
|||||||
* Initialize the encryption method corresponding to the given hash algorithm.
|
* Initialize the encryption method corresponding to the given hash algorithm.
|
||||||
*
|
*
|
||||||
* @param algorithm The algorithm to retrieve the encryption method for
|
* @param algorithm The algorithm to retrieve the encryption method for
|
||||||
|
*
|
||||||
* @return The associated encryption method
|
* @return The associated encryption method
|
||||||
*/
|
*/
|
||||||
private static EncryptionMethod initializeEncryptionMethodWithoutEvent(HashAlgorithm algorithm) {
|
private static EncryptionMethod initializeEncryptionMethodWithoutEvent(HashAlgorithm algorithm) {
|
||||||
@ -116,13 +114,9 @@ public class PasswordSecurity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hashPasswordForNewAlgorithm(String password, String playerName) {
|
private void hashPasswordForNewAlgorithm(String password, String playerName) {
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
|
||||||
if (auth != null) {
|
|
||||||
HashedPassword hashedPassword = initializeEncryptionMethod(algorithm, playerName)
|
HashedPassword hashedPassword = initializeEncryptionMethod(algorithm, playerName)
|
||||||
.computeHash(password, playerName);
|
.computeHash(password, playerName);
|
||||||
auth.setPassword(hashedPassword);
|
dataSource.updatePassword(playerName, hashedPassword);
|
||||||
dataSource.updatePassword(auth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,18 @@
|
|||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
package fr.xephi.authme.security.crypts;
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* BCrypt implements OpenBSD-style Blowfish password hashing using the scheme
|
* BCrypt implements OpenBSD-style Blowfish password hashing using the scheme
|
||||||
@ -64,6 +65,7 @@ import fr.xephi.authme.util.StringUtils;
|
|||||||
* is twice as much work. The default log_rounds is 10, and the valid range is 4
|
* is twice as much work. The default log_rounds is 10, and the valid range is 4
|
||||||
* to 31.
|
* to 31.
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
* @author Damien Miller
|
* @author Damien Miller
|
||||||
* @version 0.2
|
* @version 0.2
|
||||||
*/
|
*/
|
||||||
@ -103,7 +105,9 @@ public class BCRYPT implements EncryptionMethod {
|
|||||||
* @param d the byte array to encode
|
* @param d the byte array to encode
|
||||||
* @param len the number of bytes to encode
|
* @param len the number of bytes to encode
|
||||||
*
|
*
|
||||||
* @return base64-encoded string * @throws IllegalArgumentException if the length is invalid * @throws IllegalArgumentException
|
* @return base64-encoded string
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the length is invalid
|
||||||
*/
|
*/
|
||||||
private static String encode_base64(byte d[], int len)
|
private static String encode_base64(byte d[], int len)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
@ -161,6 +165,7 @@ public class BCRYPT implements EncryptionMethod {
|
|||||||
* @param maxolen the maximum number of bytes to decode
|
* @param maxolen the maximum number of bytes to decode
|
||||||
*
|
*
|
||||||
* @return an array containing the decoded bytes
|
* @return an array containing the decoded bytes
|
||||||
|
*
|
||||||
* @throws IllegalArgumentException if maxolen is invalid
|
* @throws IllegalArgumentException if maxolen is invalid
|
||||||
*/
|
*/
|
||||||
private static byte[] decode_base64(String s, int maxolen)
|
private static byte[] decode_base64(String s, int maxolen)
|
||||||
|
22
src/main/java/fr/xephi/authme/security/crypts/XFBCRYPT.java
Normal file
22
src/main/java/fr/xephi/authme/security/crypts/XFBCRYPT.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class XFBCRYPT extends BCRYPT {
|
||||||
|
private static final Pattern HASH_PATTERN = Pattern.compile("\"hash\";s.*\"(.*)?\"");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateSalt() {
|
||||||
|
return BCRYPT.gensalt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHashFromBlob(byte[] blob) {
|
||||||
|
String line = new String(blob);
|
||||||
|
Matcher m = HASH_PATTERN.matcher(line);
|
||||||
|
if (m.find()) {
|
||||||
|
return m.group(1);
|
||||||
|
}
|
||||||
|
return "*"; // what?
|
||||||
|
}
|
||||||
|
}
|
@ -515,11 +515,6 @@ public final class Settings {
|
|||||||
set("Xenoforo.predefinedSalt", null);
|
set("Xenoforo.predefinedSalt", null);
|
||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
if (configFile.getString("settings.security.passwordHash", "SHA256").toUpperCase().equals("XFSHA1") ||
|
|
||||||
configFile.getString("settings.security.passwordHash", "SHA256").toUpperCase().equals("XFSHA256")) {
|
|
||||||
set("settings.security.passwordHash", "XENFORO");
|
|
||||||
changes = true;
|
|
||||||
}
|
|
||||||
if (!contains("Protection.enableProtection")) {
|
if (!contains("Protection.enableProtection")) {
|
||||||
set("Protection.enableProtection", false);
|
set("Protection.enableProtection", false);
|
||||||
changes = true;
|
changes = true;
|
||||||
@ -528,10 +523,6 @@ public final class Settings {
|
|||||||
set("settings.restrictions.removeSpeed", true);
|
set("settings.restrictions.removeSpeed", true);
|
||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
if (!contains("DataSource.mySQLMaxConections")) {
|
|
||||||
set("DataSource.mySQLMaxConections", 25);
|
|
||||||
changes = true;
|
|
||||||
}
|
|
||||||
if (!contains("Protection.countries")) {
|
if (!contains("Protection.countries")) {
|
||||||
countries = new ArrayList<>();
|
countries = new ArrayList<>();
|
||||||
countries.add("US");
|
countries.add("US");
|
||||||
@ -741,6 +732,7 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changes) {
|
if (changes) {
|
||||||
|
save();
|
||||||
plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
|
plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
|
||||||
plugin.getLogger().warning("Please check your config.yml file for new configs!");
|
plugin.getLogger().warning("Please check your config.yml file for new configs!");
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -10,6 +10,7 @@ import fr.xephi.authme.security.crypts.PHPBB;
|
|||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
@ -70,9 +71,7 @@ public class PasswordSecurityTest {
|
|||||||
String playerLowerCase = playerName.toLowerCase();
|
String playerLowerCase = playerName.toLowerCase();
|
||||||
String clearTextPass = "myPassTest";
|
String clearTextPass = "myPassTest";
|
||||||
|
|
||||||
PlayerAuth auth = mock(PlayerAuth.class);
|
given(dataSource.getPassword(playerName)).willReturn(password);
|
||||||
given(auth.getPassword()).willReturn(password);
|
|
||||||
given(dataSource.getAuth(playerName)).willReturn(auth);
|
|
||||||
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(true);
|
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(true);
|
||||||
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.BCRYPT, pluginManager, false);
|
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.BCRYPT, pluginManager, false);
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ public class PasswordSecurityTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(true));
|
assertThat(result, equalTo(true));
|
||||||
verify(dataSource).getAuth(playerName);
|
verify(dataSource).getPassword(playerName);
|
||||||
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
|
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
|
||||||
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
||||||
}
|
}
|
||||||
@ -95,8 +94,7 @@ public class PasswordSecurityTest {
|
|||||||
String clearTextPass = "passw0Rd1";
|
String clearTextPass = "passw0Rd1";
|
||||||
|
|
||||||
PlayerAuth auth = mock(PlayerAuth.class);
|
PlayerAuth auth = mock(PlayerAuth.class);
|
||||||
given(auth.getPassword()).willReturn(password);
|
given(dataSource.getPassword(playerName)).willReturn(password);
|
||||||
given(dataSource.getAuth(playerName)).willReturn(auth);
|
|
||||||
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
|
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
|
||||||
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.CUSTOM, pluginManager, false);
|
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.CUSTOM, pluginManager, false);
|
||||||
|
|
||||||
@ -105,7 +103,7 @@ public class PasswordSecurityTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(false));
|
assertThat(result, equalTo(false));
|
||||||
verify(dataSource).getAuth(playerName);
|
verify(dataSource).getPassword(playerName);
|
||||||
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
|
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
|
||||||
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
||||||
}
|
}
|
||||||
@ -116,7 +114,7 @@ public class PasswordSecurityTest {
|
|||||||
String playerName = "bobby";
|
String playerName = "bobby";
|
||||||
String clearTextPass = "tables";
|
String clearTextPass = "tables";
|
||||||
|
|
||||||
given(dataSource.getAuth(playerName)).willReturn(null);
|
given(dataSource.getPassword(playerName)).willReturn(null);
|
||||||
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.MD5, pluginManager, false);
|
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.MD5, pluginManager, false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -124,7 +122,7 @@ public class PasswordSecurityTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(false));
|
assertThat(result, equalTo(false));
|
||||||
verify(dataSource).getAuth(playerName);
|
verify(dataSource).getPassword(playerName);
|
||||||
verify(pluginManager, never()).callEvent(any(Event.class));
|
verify(pluginManager, never()).callEvent(any(Event.class));
|
||||||
verify(method, never()).comparePassword(anyString(), any(HashedPassword.class), anyString());
|
verify(method, never()).comparePassword(anyString(), any(HashedPassword.class), anyString());
|
||||||
}
|
}
|
||||||
@ -141,11 +139,7 @@ public class PasswordSecurityTest {
|
|||||||
// MD5 hash for "Test"
|
// MD5 hash for "Test"
|
||||||
HashedPassword newPassword = new HashedPassword("0cbc6611f5540bd0809a388dc95a615b");
|
HashedPassword newPassword = new HashedPassword("0cbc6611f5540bd0809a388dc95a615b");
|
||||||
|
|
||||||
PlayerAuth auth = mock(PlayerAuth.class);
|
given(dataSource.getPassword(argThat(equalToIgnoringCase(playerName)))).willReturn(password);
|
||||||
doCallRealMethod().when(auth).getPassword();
|
|
||||||
doCallRealMethod().when(auth).setPassword(any(HashedPassword.class));
|
|
||||||
auth.setPassword(password);
|
|
||||||
given(dataSource.getAuth(argThat(equalToIgnoringCase(playerName)))).willReturn(auth);
|
|
||||||
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
|
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
|
||||||
given(method.computeHash(clearTextPass, playerLowerCase)).willReturn(newPassword);
|
given(method.computeHash(clearTextPass, playerLowerCase)).willReturn(newPassword);
|
||||||
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.MD5, pluginManager, true);
|
PasswordSecurity security = new PasswordSecurity(dataSource, HashAlgorithm.MD5, pluginManager, true);
|
||||||
@ -158,14 +152,10 @@ public class PasswordSecurityTest {
|
|||||||
// Note ljacqu 20151230: We need to check the player name in a case-insensitive way because the methods within
|
// Note ljacqu 20151230: We need to check the player name in a case-insensitive way because the methods within
|
||||||
// PasswordSecurity may convert the name into all lower-case. This is desired because EncryptionMethod methods
|
// PasswordSecurity may convert the name into all lower-case. This is desired because EncryptionMethod methods
|
||||||
// should only be invoked with all lower-case names. Data source is case-insensitive itself, so this is fine.
|
// should only be invoked with all lower-case names. Data source is case-insensitive itself, so this is fine.
|
||||||
verify(dataSource, times(2)).getAuth(argThat(equalToIgnoringCase(playerName)));
|
verify(dataSource).getPassword(argThat(equalToIgnoringCase(playerName)));
|
||||||
verify(pluginManager, times(2)).callEvent(any(PasswordEncryptionEvent.class));
|
verify(pluginManager, times(2)).callEvent(any(PasswordEncryptionEvent.class));
|
||||||
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
|
||||||
verify(auth).setPassword(newPassword);
|
verify(dataSource).updatePassword(playerLowerCase, newPassword);
|
||||||
|
|
||||||
ArgumentCaptor<PlayerAuth> captor = ArgumentCaptor.forClass(PlayerAuth.class);
|
|
||||||
verify(dataSource).updatePassword(captor.capture());
|
|
||||||
assertThat(captor.getValue().getPassword(), equalTo(newPassword));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2,15 +2,15 @@ package fr.xephi.authme.security.crypts;
|
|||||||
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.util.WrapperMock;
|
import fr.xephi.authme.util.WrapperMock;
|
||||||
import org.junit.Before;
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link BCRYPT}.
|
* Test for {@link BCRYPT}.
|
||||||
*/
|
*/
|
||||||
public class BcryptTest extends AbstractEncryptionMethodTest {
|
public class BcryptTest extends AbstractEncryptionMethodTest {
|
||||||
|
|
||||||
@Before
|
@BeforeClass
|
||||||
public void setUpSettings() {
|
public static void setUpSettings() {
|
||||||
WrapperMock.createInstance();
|
WrapperMock.createInstance();
|
||||||
Settings.bCryptLog2Rounds = 8;
|
Settings.bCryptLog2Rounds = 8;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import fr.xephi.authme.util.WrapperMock;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link XFBCRYPT}.
|
||||||
|
*/
|
||||||
|
public class XFBCRYPTTest extends AbstractEncryptionMethodTest {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpWrapper() {
|
||||||
|
WrapperMock.createInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XFBCRYPTTest() {
|
||||||
|
super(new XFBCRYPT(),
|
||||||
|
"$2a$10$UtuON/ZG.x8EWG/zQbryB.BHfQVrfxk3H7qykzP.UJQ8YiLjZyfqq", // password
|
||||||
|
"$2a$10$Q.ocUo.YtHTdI4nu3pcpKun6BILcmWHm541ANULucmuU/ps1QKY4K", // PassWord1
|
||||||
|
"$2a$10$yHjm02.K4HP5iFU1F..yLeTeo7PWZVbKAr/QGex5jU4.J3mdq/uuO", // &^%te$t?Pw@_
|
||||||
|
"$2a$10$joIayhGStExKWxNbiqMMPOYFSpQ76HVNjpOB7.QwTmG5q.TiJJ.0e"); // âË_3(íù*
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user