Merge branch 'master' of https://github.com/AuthMe-Team/AuthMeReloaded into 347-config-rewrite

This commit is contained in:
ljacqu 2016-01-09 23:07:20 +01:00
commit 4321d0b938
13 changed files with 73 additions and 74 deletions

View File

@ -79,6 +79,7 @@ typing commands or using the inventory. It can also kick players with uncommonly
<li>Supported alternative registration methods:<br> <li>Supported alternative registration methods:<br>
<ul> <ul>
<li>PHPBB, VBulletin: MD5VB - PHPBB</li> <li>PHPBB, VBulletin: MD5VB - PHPBB</li>
<li>Xenforo: XFBCRYPT</li>
<li>MyBB: MYBB</li> <li>MyBB: MYBB</li>
<li>IPB3: IPB3</li> <li>IPB3: IPB3</li>
<li>PhpFusion: PHPFUSION</li> <li>PhpFusion: PHPFUSION</li>

View File

@ -27,12 +27,7 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
// Validate the password // Validate the password
String playerPassLowerCase = playerPass.toLowerCase(); String playerPassLowerCase = playerPass.toLowerCase();
// TODO #308: Remove this check if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where")
|| playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify")
|| playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select")
|| playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null")
|| !playerPassLowerCase.matches(Settings.getPassRegex)) {
commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR); commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
return; return;
} }

View File

@ -27,12 +27,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
final String playerPassLowerCase = playerPass.toLowerCase(); final String playerPassLowerCase = playerPass.toLowerCase();
// Command logic // Command logic
// TODO #308: Remove the check for SQL keywords if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where")
|| playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify")
|| playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select")
|| playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null")
|| !playerPassLowerCase.matches(Settings.getPassRegex)) {
commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR); commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
return; return;
} }

View File

@ -32,12 +32,7 @@ public class ChangePasswordCommand extends PlayerCommand {
// Make sure the password is allowed // Make sure the password is allowed
String playerPassLowerCase = newPassword.toLowerCase(); String playerPassLowerCase = newPassword.toLowerCase();
// TODO #308: Remove SQL keywords check if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where")
|| playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify")
|| playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select")
|| playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null")
|| !playerPassLowerCase.matches(Settings.getPassRegex)) {
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR); commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return; return;
} }

View File

@ -104,7 +104,12 @@ public class MySQL implements DataSource {
ds = new HikariDataSource(); ds = new HikariDataSource();
ds.setPoolName("AuthMeMYSQLPool"); ds.setPoolName("AuthMeMYSQLPool");
ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database + "?rewriteBatchedStatements=true&jdbcCompliantTruncation=false"); ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
ds.addDataSourceProperty("rewriteBatchedStatements", "true");
ds.addDataSourceProperty("jdbcCompliantTruncation", "false");
ds.addDataSourceProperty("cachePrepStmts", "true");
ds.addDataSourceProperty("prepStmtCacheSize", "250");
ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
ds.setUsername(this.username); ds.setUsername(this.username);
ds.setPassword(this.password); ds.setPassword(this.password);
ds.setInitializationFailFast(true); // Don't start the plugin if the database is unavailable ds.setInitializationFailFast(true); // Don't start the plugin if the database is unavailable
@ -329,17 +334,18 @@ public class MySQL implements DataSource {
boolean useSalt = !columnSalt.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt()); boolean useSalt = !columnSalt.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt());
sql = "INSERT INTO " + tableName + "(" sql = "INSERT INTO " + tableName + "("
+ columnName + "," + columnPassword + "," + columnIp + "," + columnName + "," + columnPassword + "," + columnIp + ","
+ columnLastLogin + "," + columnRealName + columnLastLogin + "," + columnRealName + "," + columnEmail
+ (useSalt ? "," + columnSalt : "") + (useSalt ? "," + columnSalt : "")
+ ") VALUES (?,?,?,?,?" + (useSalt ? ",?" : "") + ");"; + ") VALUES (?,?,?,?,?,?" + (useSalt ? ",?" : "") + ");";
pst = con.prepareStatement(sql); pst = con.prepareStatement(sql);
pst.setString(1, auth.getNickname()); pst.setString(1, auth.getNickname());
pst.setString(2, auth.getPassword().getHash()); pst.setString(2, auth.getPassword().getHash());
pst.setString(3, auth.getIp()); pst.setString(3, auth.getIp());
pst.setLong(4, auth.getLastLogin()); pst.setLong(4, auth.getLastLogin());
pst.setString(5, auth.getRealName()); pst.setString(5, auth.getRealName());
pst.setString(6, auth.getEmail());
if (useSalt) { if (useSalt) {
pst.setString(6, auth.getPassword().getSalt()); pst.setString(7, auth.getPassword().getSalt());
} }
pst.executeUpdate(); pst.executeUpdate();
pst.close(); pst.close();
@ -496,10 +502,12 @@ public class MySQL implements DataSource {
rs = pst.executeQuery(); rs = pst.executeQuery();
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(columnID); int id = rs.getInt(columnID);
pst2 = con.prepareStatement("INSERT INTO xf_user_authenticate (user_id, scheme_class, data) VALUES (?,?,?);"); sql = "INSERT INTO xf_user_authenticate (user_id, scheme_class, data) VALUES (?,?,?)";
pst2 = con.prepareStatement(sql);
pst2.setInt(1, id); pst2.setInt(1, id);
pst2.setString(2, "XenForo_Authentication_Core12"); pst2.setString(2, XFBCRYPT.SCHEME_CLASS);
byte[] bytes = auth.getPassword().getHash().getBytes(); String serializedHash = XFBCRYPT.serializeHash(auth.getPassword().getHash());
byte[] bytes = serializedHash.getBytes();
Blob blob = con.createBlob(); Blob blob = con.createBlob();
blob.setBytes(1, bytes); blob.setBytes(1, bytes);
pst2.setBlob(3, blob); pst2.setBlob(3, blob);
@ -554,7 +562,8 @@ public class MySQL implements DataSource {
// Insert password in the correct table // Insert password in the correct table
sql = "UPDATE xf_user_authenticate SET data=? WHERE " + columnID + "=?;"; sql = "UPDATE xf_user_authenticate SET data=? WHERE " + columnID + "=?;";
PreparedStatement pst2 = con.prepareStatement(sql); PreparedStatement pst2 = con.prepareStatement(sql);
byte[] bytes = password.getHash().getBytes(); String serializedHash = XFBCRYPT.serializeHash(password.getHash());
byte[] bytes = serializedHash.getBytes();
Blob blob = con.createBlob(); Blob blob = con.createBlob();
blob.setBytes(1, bytes); blob.setBytes(1, bytes);
pst2.setBlob(1, blob); pst2.setBlob(1, blob);
@ -564,7 +573,7 @@ public class MySQL implements DataSource {
// ... // ...
sql = "UPDATE xf_user_authenticate SET scheme_class=? WHERE " + columnID + "=?;"; sql = "UPDATE xf_user_authenticate SET scheme_class=? WHERE " + columnID + "=?;";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.setString(1, "XenForo_Authentication_Core12"); pst2.setString(1, XFBCRYPT.SCHEME_CLASS);
pst2.setInt(2, id); pst2.setInt(2, id);
pst2.executeUpdate(); pst2.executeUpdate();
pst2.close(); pst2.close();
@ -618,15 +627,18 @@ public class MySQL implements DataSource {
public synchronized List<String> autoPurgeDatabase(long until) { public synchronized List<String> autoPurgeDatabase(long until) {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
try (Connection con = getConnection()) { try (Connection con = getConnection()) {
String sql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + columnLastLogin + "<" + until; String sql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + columnLastLogin + "<?;";
Statement st = con.createStatement(); PreparedStatement st = con.prepareStatement(sql);
ResultSet rs = st.executeQuery(sql); st.setLong(1, until);
ResultSet rs = st.executeQuery();
while (rs.next()) { while (rs.next()) {
list.add(rs.getString(columnName)); list.add(rs.getString(columnName));
} }
rs.close(); rs.close();
sql = "DELETE FROM " + tableName + " WHERE " + columnLastLogin + "<" + until; sql = "DELETE FROM " + tableName + " WHERE " + columnLastLogin + "<?;";
st.executeUpdate(sql); st = con.prepareStatement(sql);
st.setLong(1, until);
st.executeUpdate();
st.close(); st.close();
} catch (SQLException ex) { } catch (SQLException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
@ -648,9 +660,10 @@ public class MySQL implements DataSource {
ResultSet rs = pst.executeQuery(); ResultSet rs = pst.executeQuery();
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(columnID); int id = rs.getInt(columnID);
sql = "DELETE FROM xf_user_authenticate WHERE " + columnID + "=" + id; sql = "DELETE FROM xf_user_authenticate WHERE " + columnID + "=?;";
Statement st = con.createStatement(); PreparedStatement st = con.prepareStatement(sql);
st.executeUpdate(sql); st.setInt(1, id);
st.executeUpdate();
st.close(); st.close();
} }
rs.close(); rs.close();

View File

@ -1,5 +1,11 @@
package fr.xephi.authme.datasource; package fr.xephi.authme.datasource;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -9,12 +15,6 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
/** /**
*/ */
public class SQLite implements DataSource { public class SQLite implements DataSource {
@ -219,23 +219,26 @@ public class SQLite implements DataSource {
+ "is not set in the config!"); + "is not set in the config!");
} }
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword +
"," + columnIp + "," + columnLastLogin + "," + columnRealName + ") VALUES (?,?,?,?,?);"); "," + columnIp + "," + columnLastLogin + "," + columnRealName + "," + columnEmail +
") VALUES (?,?,?,?,?,?);");
pst.setString(1, auth.getNickname()); pst.setString(1, auth.getNickname());
pst.setString(2, password.getHash()); pst.setString(2, password.getHash());
pst.setString(3, auth.getIp()); pst.setString(3, auth.getIp());
pst.setLong(4, auth.getLastLogin()); pst.setLong(4, auth.getLastLogin());
pst.setString(5, auth.getRealName()); pst.setString(5, auth.getRealName());
pst.setString(6, auth.getEmail());
pst.executeUpdate(); pst.executeUpdate();
} else { } else {
pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + "," pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + ","
+ columnIp + "," + columnLastLogin + "," + columnSalt + "," + columnRealName + columnIp + "," + columnLastLogin + "," + columnRealName + "," + columnEmail + "," + columnSalt
+ ") VALUES (?,?,?,?,?,?);"); + ") VALUES (?,?,?,?,?,?,?);");
pst.setString(1, auth.getNickname()); pst.setString(1, auth.getNickname());
pst.setString(2, password.getHash()); pst.setString(2, password.getHash());
pst.setString(3, auth.getIp()); pst.setString(3, auth.getIp());
pst.setLong(4, auth.getLastLogin()); pst.setLong(4, auth.getLastLogin());
pst.setString(5, password.getSalt()); pst.setString(5, auth.getRealName());
pst.setString(6, auth.getRealName()); pst.setString(6, auth.getEmail());
pst.setString(7, password.getSalt());
pst.executeUpdate(); pst.executeUpdate();
} }
} catch (SQLException ex) { } catch (SQLException ex) {

View File

@ -185,7 +185,7 @@ public class AuthMePlayerListener implements Listener {
} }
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOW)
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (player == null) { if (player == null) {

View File

@ -2,21 +2,18 @@ package fr.xephi.authme.output;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.CustomConfiguration; import fr.xephi.authme.settings.CustomConfiguration;
import org.bukkit.ChatColor;
import java.io.File; import java.io.File;
/** /**
* Class responsible for reading messages from a file and formatting them for Minecraft. * Class responsible for reading messages from a file and formatting them for Minecraft.
* <p /> * <p>
* This class is used within {@link Messages}, which offers a high-level interface for accessing * This class is used within {@link Messages}, which offers a high-level interface for accessing
* or sending messages from a properties file. * or sending messages from a properties file.
*/ */
class MessagesManager extends CustomConfiguration { class MessagesManager extends CustomConfiguration {
/** The section symbol, used in Minecraft for formatting codes. */
private static final String SECTION_SIGN = "\u00a7";
/** /**
* Constructor for Messages. * Constructor for Messages.
* *
@ -49,12 +46,10 @@ class MessagesManager extends CustomConfiguration {
} }
static String[] formatMessage(String message) { static String[] formatMessage(String message) {
// TODO: Check that the codes actually exist, i.e. replace &c but not &y
// TODO: Allow '&' to be retained with the code '&&'
String[] lines = message.split("&n"); String[] lines = message.split("&n");
for (int i = 0; i < lines.length; ++i) { for (int i = 0; i < lines.length; ++i) {
// We don't initialize a StringBuilder here because mostly we will only have one entry // We don't initialize a StringBuilder here because mostly we will only have one entry
lines[i] = lines[i].replace("&", SECTION_SIGN); lines[i] = ChatColor.translateAlternateColorCodes('&', lines[i]);
} }
return lines; return lines;
} }

View File

@ -83,7 +83,12 @@ public enum PlayerPermission implements PermissionNode {
/** /**
* Permission to use all player (non-admin) commands. * Permission to use all player (non-admin) commands.
*/ */
PLAYER_ALL("authme.player.*"); PLAYER_ALL("authme.player.*"),
/**
* Permission to use to see own other accounts.
*/
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts");
/** /**
* The permission node. * The permission node.

View File

@ -223,8 +223,6 @@ public class AsynchronousLogin {
return; return;
} }
List<String> auths = this.database.getAllAuthsByName(auth); List<String> auths = this.database.getAllAuthsByName(auth);
// List<String> uuidlist =
// plugin.otherAccounts.getAllPlayersByUUID(player.getUniqueId());
if (auths.isEmpty()) { if (auths.isEmpty()) {
return; return;
} }
@ -232,8 +230,6 @@ public class AsynchronousLogin {
return; return;
} }
StringBuilder message = new StringBuilder("[AuthMe] "); StringBuilder message = new StringBuilder("[AuthMe] ");
// String uuidaccounts =
// "[AuthMe] PlayerNames has %size% links to this UUID : ";
int i = 0; int i = 0;
for (String account : auths) { for (String account : auths) {
i++; i++;
@ -244,18 +240,13 @@ public class AsynchronousLogin {
message.append('.'); message.append('.');
} }
} }
/*
* TODO: Active uuid system i = 0; for (String account : uuidlist) {
* i++; uuidaccounts = uuidaccounts + account; if (i != auths.size()) {
* uuidaccounts = uuidaccounts + ", "; } else { uuidaccounts =
* uuidaccounts + "."; } }
*/
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OTHER_ACCOUNTS)) { if (plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts"); player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts");
player.sendMessage(message.toString()); player.sendMessage(message.toString());
// player.sendMessage(uuidaccounts.replace("%size%",
// ""+uuidlist.size()));
} }
} }
} }

View File

@ -44,10 +44,7 @@ public class AsyncRegister {
} else if (!Settings.isRegistrationEnabled) { } else if (!Settings.isRegistrationEnabled) {
m.send(player, MessageKey.REGISTRATION_DISABLED); m.send(player, MessageKey.REGISTRATION_DISABLED);
return false; return false;
} else if (passLow.contains("delete") || passLow.contains("where") || passLow.contains("insert") } else if (!passLow.matches(Settings.getPassRegex)) {
|| passLow.contains("modify") || passLow.contains("from") || passLow.contains("select")
|| passLow.contains(";") || passLow.contains("null") || !passLow.matches(Settings.getPassRegex)) {
// TODO #308: Remove check for SQL keywords
m.send(player, MessageKey.PASSWORD_MATCH_ERROR); m.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return false; return false;
} else if (passLow.equalsIgnoreCase(player.getName())) { } else if (passLow.equalsIgnoreCase(player.getName())) {

View File

@ -4,6 +4,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class XFBCRYPT extends BCRYPT { public class XFBCRYPT extends BCRYPT {
public static final String SCHEME_CLASS = "XenForo_Authentication_Core12";
private static final Pattern HASH_PATTERN = Pattern.compile("\"hash\";s.*\"(.*)?\""); private static final Pattern HASH_PATTERN = Pattern.compile("\"hash\";s.*\"(.*)?\"");
@Override @Override
@ -19,4 +20,8 @@ public class XFBCRYPT extends BCRYPT {
} }
return "*"; // what? return "*"; // what?
} }
public static String serializeHash(String hash) {
return "a:1:{s:4:\"hash\";s:" + hash.length() + ":\""+hash+"\";}";
}
} }

View File

@ -141,6 +141,7 @@ permissions:
authme.player.seeotheraccounts: true authme.player.seeotheraccounts: true
authme.player.unregister: true authme.player.unregister: true
authme.player.vip: true authme.player.vip: true
authme.player.seeownaccounts: true
authme.player.bypassantibot: authme.player.bypassantibot:
description: Permission node to bypass AntiBot protection. description: Permission node to bypass AntiBot protection.
default: false default: false
@ -186,3 +187,6 @@ permissions:
authme.player.seeotheraccounts: authme.player.seeotheraccounts:
description: Permission for user to see other accounts. description: Permission for user to see other accounts.
default: false default: false
authme.player.seeownaccounts:
description: Permission for user to see own other accounts.
default: false