Merge branch 'master' into 137-xenforo-support
Conflicts: src/main/java/fr/xephi/authme/datasource/CacheDataSource.java src/main/java/fr/xephi/authme/datasource/DataSource.java src/main/java/fr/xephi/authme/datasource/SQLite.java src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
This commit is contained in:
commit
e0c3affa33
@ -1,6 +1,8 @@
|
|||||||
package fr.xephi.authme;
|
package fr.xephi.authme;
|
||||||
|
|
||||||
import com.earth2me.essentials.Essentials;
|
import com.earth2me.essentials.Essentials;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.io.Resources;
|
||||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||||
import fr.xephi.authme.api.API;
|
import fr.xephi.authme.api.API;
|
||||||
import fr.xephi.authme.api.NewAPI;
|
import fr.xephi.authme.api.NewAPI;
|
||||||
@ -30,7 +32,6 @@ import fr.xephi.authme.listener.AuthMePlayerListener;
|
|||||||
import fr.xephi.authme.listener.AuthMePlayerListener16;
|
import fr.xephi.authme.listener.AuthMePlayerListener16;
|
||||||
import fr.xephi.authme.listener.AuthMePlayerListener18;
|
import fr.xephi.authme.listener.AuthMePlayerListener18;
|
||||||
import fr.xephi.authme.listener.AuthMeServerListener;
|
import fr.xephi.authme.listener.AuthMeServerListener;
|
||||||
import fr.xephi.authme.listener.AuthMeServerStop;
|
|
||||||
import fr.xephi.authme.listener.AuthMeTabCompletePacketAdapter;
|
import fr.xephi.authme.listener.AuthMeTabCompletePacketAdapter;
|
||||||
import fr.xephi.authme.mail.SendMailSSL;
|
import fr.xephi.authme.mail.SendMailSSL;
|
||||||
import fr.xephi.authme.modules.ModuleManager;
|
import fr.xephi.authme.modules.ModuleManager;
|
||||||
@ -66,11 +67,8 @@ import org.bukkit.scheduler.BukkitTask;
|
|||||||
import org.mcstats.Metrics;
|
import org.mcstats.Metrics;
|
||||||
import org.mcstats.Metrics.Graph;
|
import org.mcstats.Metrics.Graph;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -133,6 +131,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's instance.
|
* Get the plugin's instance.
|
||||||
|
*
|
||||||
* @return AuthMe
|
* @return AuthMe
|
||||||
*/
|
*/
|
||||||
public static AuthMe getInstance() {
|
public static AuthMe getInstance() {
|
||||||
@ -141,6 +140,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's name.
|
* Get the plugin's name.
|
||||||
|
*
|
||||||
* @return The plugin's name.
|
* @return The plugin's name.
|
||||||
*/
|
*/
|
||||||
public static String getPluginName() {
|
public static String getPluginName() {
|
||||||
@ -149,6 +149,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's version.
|
* Get the plugin's version.
|
||||||
|
*
|
||||||
* @return The plugin's version.
|
* @return The plugin's version.
|
||||||
*/
|
*/
|
||||||
public static String getPluginVersion() {
|
public static String getPluginVersion() {
|
||||||
@ -157,6 +158,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's build number.
|
* Get the plugin's build number.
|
||||||
|
*
|
||||||
* @return The plugin's build number.
|
* @return The plugin's build number.
|
||||||
*/
|
*/
|
||||||
public static String getPluginBuildNumber() {
|
public static String getPluginBuildNumber() {
|
||||||
@ -165,6 +167,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's Settings.
|
* Get the plugin's Settings.
|
||||||
|
*
|
||||||
* @return Plugin's settings.
|
* @return Plugin's settings.
|
||||||
*/
|
*/
|
||||||
public Settings getSettings() {
|
public Settings getSettings() {
|
||||||
@ -173,6 +176,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Messages instance.
|
* Get the Messages instance.
|
||||||
|
*
|
||||||
* @return Plugin's messages.
|
* @return Plugin's messages.
|
||||||
*/
|
*/
|
||||||
public Messages getMessages() {
|
public Messages getMessages() {
|
||||||
@ -272,7 +276,6 @@ public class AuthMe extends JavaPlugin {
|
|||||||
new PerformBackup(plugin).doBackup(PerformBackup.BackupCause.START);
|
new PerformBackup(plugin).doBackup(PerformBackup.BackupCause.START);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Setup the inventory backup
|
// Setup the inventory backup
|
||||||
playerBackup = new JsonCache();
|
playerBackup = new JsonCache();
|
||||||
|
|
||||||
@ -303,13 +306,6 @@ public class AuthMe extends JavaPlugin {
|
|||||||
// Show settings warnings
|
// Show settings warnings
|
||||||
showSettingsWarnings();
|
showSettingsWarnings();
|
||||||
|
|
||||||
// Register a server shutdown hook
|
|
||||||
try {
|
|
||||||
Runtime.getRuntime().addShutdownHook(new AuthMeServerStop(this));
|
|
||||||
} catch (Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sponsor messages
|
// Sponsor messages
|
||||||
ConsoleLogger.info("AuthMe hooks perfectly with the VeryGames server hosting!");
|
ConsoleLogger.info("AuthMe hooks perfectly with the VeryGames server hosting!");
|
||||||
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
|
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
|
||||||
@ -435,7 +431,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
// Set up the API
|
// Set up the API
|
||||||
api = new NewAPI(this);
|
api = new NewAPI(this);
|
||||||
|
|
||||||
// Setup the old deprecated API
|
// Set up the deprecated API
|
||||||
new API(this);
|
new API(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,10 +513,10 @@ public class AuthMe extends JavaPlugin {
|
|||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
// Save player data
|
// Save player data
|
||||||
Collection<? extends Player> players = Utils.getOnlinePlayers();
|
Collection<? extends Player> players = Utils.getOnlinePlayers();
|
||||||
if (players != null) {
|
for (Player player : players) {
|
||||||
for (Player player : players) {
|
savePlayer(player);
|
||||||
this.savePlayer(player);
|
// TODO: add a MessageKey
|
||||||
}
|
player.kickPlayer("Server is restarting or AuthMe plugin was disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do backup on stop if enabled
|
// Do backup on stop if enabled
|
||||||
@ -593,16 +589,16 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
// TODO: Move this to another place maybe ?
|
// TODO: Move this to another place maybe ?
|
||||||
if (Settings.getPasswordHash == HashAlgorithm.PLAINTEXT) {
|
if (Settings.getPasswordHash == HashAlgorithm.PLAINTEXT) {
|
||||||
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
|
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
|
||||||
"it will be changed and hashed now to the AuthMe default hashing method");
|
"it will be changed and hashed now to the AuthMe default hashing method");
|
||||||
for (PlayerAuth auth : database.getAllAuths()) {
|
for (PlayerAuth auth : database.getAllAuths()) {
|
||||||
HashedPassword hashedPassword = passwordSecurity.computeHash(
|
HashedPassword hashedPassword = passwordSecurity.computeHash(
|
||||||
HashAlgorithm.SHA256, auth.getPassword().getHash(), auth.getNickname());
|
HashAlgorithm.SHA256, auth.getPassword().getHash(), auth.getNickname());
|
||||||
auth.setPassword(hashedPassword);
|
auth.setPassword(hashedPassword);
|
||||||
database.updatePassword(auth);
|
database.updatePassword(auth);
|
||||||
}
|
}
|
||||||
Settings.setValue("settings.security.passwordHash", "SHA256");
|
Settings.setValue("settings.security.passwordHash", "SHA256");
|
||||||
Settings.reload();
|
Settings.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.isCachingEnabled) {
|
if (Settings.isCachingEnabled) {
|
||||||
@ -715,10 +711,9 @@ public class AuthMe extends JavaPlugin {
|
|||||||
inventoryProtector = null;
|
inventoryProtector = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tabComplete == null)
|
if (tabComplete == null) {
|
||||||
{
|
tabComplete = new AuthMeTabCompletePacketAdapter(this);
|
||||||
tabComplete = new AuthMeTabCompletePacketAdapter(this);
|
tabComplete.register();
|
||||||
tabComplete.register();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,50 +884,34 @@ public class AuthMe extends JavaPlugin {
|
|||||||
* Gets a player's real IP through VeryGames method.
|
* Gets a player's real IP through VeryGames method.
|
||||||
*
|
*
|
||||||
* @param player The player to process.
|
* @param player The player to process.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void getVerygamesIp(final Player player) {
|
public void getVerygamesIp(final Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
String currentIp = player.getAddress().getAddress().getHostAddress();
|
||||||
@Override
|
if (realIp.containsKey(name)) {
|
||||||
public void run() {
|
currentIp = realIp.get(name);
|
||||||
String realIP = player.getAddress().getAddress().getHostAddress();
|
}
|
||||||
if (realIp.containsKey(name))
|
String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%";
|
||||||
realIP = realIp.get(name);
|
sUrl = sUrl.replace("%IP%", currentIp).replace("%PORT%", "" + player.getAddress().getPort());
|
||||||
String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%";
|
try {
|
||||||
sUrl = sUrl.replace("%IP%", realIP)
|
String result = Resources.toString(new URL(sUrl), Charsets.UTF_8);
|
||||||
.replace("%PORT%", "" + player.getAddress().getPort());
|
if (!StringUtils.isEmpty(result) && !result.equalsIgnoreCase("error") && !result.contains("error")) {
|
||||||
try {
|
currentIp = result;
|
||||||
URL url = new URL(sUrl);
|
realIp.put(name, currentIp);
|
||||||
URLConnection urlCon = url.openConnection();
|
}
|
||||||
urlCon.setConnectTimeout(5000);
|
} catch (IOException e) {
|
||||||
urlCon.setReadTimeout(5000);
|
ConsoleLogger.showError("Could not fetch Very Games API with URL '" +
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream()))) {
|
sUrl + "' - " + StringUtils.formatException(e));
|
||||||
String inputLine = in.readLine();
|
}
|
||||||
if (!StringUtils.isEmpty(inputLine) && !inputLine.equalsIgnoreCase("error")
|
|
||||||
&& !inputLine.contains("error")) {
|
|
||||||
realIP = inputLine;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
ConsoleLogger.showError("Could not read from Very Games API - " + StringUtils.formatException(e));
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
ConsoleLogger.showError("Could not fetch Very Games API with URL '" + sUrl + "' - "
|
|
||||||
+ StringUtils.formatException(e));
|
|
||||||
}
|
|
||||||
if (realIp.containsKey(name))
|
|
||||||
realIp.remove(name);
|
|
||||||
realIp.putIfAbsent(name, realIP);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIP(final Player player) {
|
public String getIP(final Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
String ip = player.getAddress().getAddress().getHostAddress();
|
String ip = player.getAddress().getAddress().getHostAddress();
|
||||||
if (realIp.containsKey(name))
|
if (realIp.containsKey(name)) {
|
||||||
ip = realIp.get(name);
|
ip = realIp.get(name);
|
||||||
|
}
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,6 +962,8 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the management instance.
|
* Return the management instance.
|
||||||
|
*
|
||||||
|
* @return management The Management
|
||||||
*/
|
*/
|
||||||
public Management getManagement() {
|
public Management getManagement() {
|
||||||
return management;
|
return management;
|
||||||
|
|||||||
@ -1,12 +1,5 @@
|
|||||||
package fr.xephi.authme;
|
package fr.xephi.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.permission.PermissionsManager;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.util.Utils;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@ -14,6 +7,14 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.util.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public class DataManager {
|
public class DataManager {
|
||||||
@ -65,7 +66,7 @@ public class DataManager {
|
|||||||
/**
|
/**
|
||||||
* Method purgeAntiXray.
|
* Method purgeAntiXray.
|
||||||
*
|
*
|
||||||
* @param cleared List<String>
|
* @param cleared List of String
|
||||||
*/
|
*/
|
||||||
public synchronized void purgeAntiXray(List<String> cleared) {
|
public synchronized void purgeAntiXray(List<String> cleared) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -90,7 +91,7 @@ public class DataManager {
|
|||||||
/**
|
/**
|
||||||
* Method purgeLimitedCreative.
|
* Method purgeLimitedCreative.
|
||||||
*
|
*
|
||||||
* @param cleared List<String>
|
* @param cleared List of String
|
||||||
*/
|
*/
|
||||||
public synchronized void purgeLimitedCreative(List<String> cleared) {
|
public synchronized void purgeLimitedCreative(List<String> cleared) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -127,7 +128,7 @@ public class DataManager {
|
|||||||
/**
|
/**
|
||||||
* Method purgeDat.
|
* Method purgeDat.
|
||||||
*
|
*
|
||||||
* @param cleared List<String>
|
* @param cleared List of String
|
||||||
*/
|
*/
|
||||||
public synchronized void purgeDat(List<String> cleared) {
|
public synchronized void purgeDat(List<String> cleared) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -160,7 +161,7 @@ public class DataManager {
|
|||||||
/**
|
/**
|
||||||
* Method purgeEssentials.
|
* Method purgeEssentials.
|
||||||
*
|
*
|
||||||
* @param cleared List<String>
|
* @param cleared List of String
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void purgeEssentials(List<String> cleared) {
|
public void purgeEssentials(List<String> cleared) {
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
package fr.xephi.authme.api;
|
package fr.xephi.authme.api;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
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 fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.util.Utils;
|
import fr.xephi.authme.util.Utils;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current API of AuthMe.
|
* The current API of AuthMe.
|
||||||
@ -76,7 +77,7 @@ public class NewAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param player
|
* @param player a Player
|
||||||
*
|
*
|
||||||
* @return true if player is a npc
|
* @return true if player is a npc
|
||||||
*/
|
*/
|
||||||
@ -85,7 +86,7 @@ public class NewAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param player
|
* @param player a Player
|
||||||
*
|
*
|
||||||
* @return true if the player is unrestricted
|
* @return true if the player is unrestricted
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
package fr.xephi.authme.cache.auth;
|
package fr.xephi.authme.cache.auth;
|
||||||
|
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
|
|
||||||
import static com.google.common.base.Objects.firstNonNull;
|
import static com.google.common.base.Objects.firstNonNull;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@ -24,7 +25,7 @@ public class PlayerAuth {
|
|||||||
private String realName;
|
private String realName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param serialized String
|
||||||
*/
|
*/
|
||||||
public PlayerAuth(String serialized) {
|
public PlayerAuth(String serialized) {
|
||||||
this.deserialize(serialized);
|
this.deserialize(serialized);
|
||||||
@ -340,6 +341,8 @@ public class PlayerAuth {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to deserialize PlayerAuth
|
* Method to deserialize PlayerAuth
|
||||||
|
*
|
||||||
|
* @param str String
|
||||||
*/
|
*/
|
||||||
public void deserialize(String str) {
|
public void deserialize(String str) {
|
||||||
String[] args = str.split(";");
|
String[] args = str.split(";");
|
||||||
|
|||||||
@ -12,12 +12,13 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command description - defines which labels ("names") will lead to a command and points to the
|
* Command description – defines which labels ("names") will lead to a command and points to the
|
||||||
* {@link ExecutableCommand} implementation that executes the logic of the command.
|
* {@link ExecutableCommand} implementation that executes the logic of the command.
|
||||||
*
|
*
|
||||||
* CommandDescription instances are built hierarchically and have one parent or {@code null} for base commands
|
* CommandDescription instances are built hierarchically: they have one parent, or {@code null} for base commands
|
||||||
* (main commands such as /authme) and may have multiple children extending the mapping of the parent: e.g. if
|
* (main commands such as {@code /authme}), and may have multiple children extending the mapping of the parent: e.g. if
|
||||||
* /authme has a child whose label is "register", then "/authme register" is the command that the child defines.
|
* {@code /authme} has a child whose label is {@code "register"}, then {@code /authme register} is the command that
|
||||||
|
* the child defines.
|
||||||
*/
|
*/
|
||||||
public class CommandDescription {
|
public class CommandDescription {
|
||||||
|
|
||||||
@ -102,10 +103,11 @@ public class CommandDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all relative labels of this command. For example, if this object describes "/authme register" and
|
* Return all relative labels of this command. For example, if this object describes {@code /authme register} and
|
||||||
* "/authme r", then "r" and "register" are the relative labels, whereas "authme" is the label of the parent.
|
* {@code /authme r}, then it will return a list with {@code register} and {@code r}. The parent label
|
||||||
|
* {@code authme} is not returned.
|
||||||
*
|
*
|
||||||
* @return All relative labels.
|
* @return All labels of the command description.
|
||||||
*/
|
*/
|
||||||
public List<String> getLabels() {
|
public List<String> getLabels() {
|
||||||
return labels;
|
return labels;
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
package fr.xephi.authme.command;
|
package fr.xephi.authme.command;
|
||||||
|
|
||||||
import fr.xephi.authme.util.StringUtils;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
|
* The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
|
||||||
* or to display help messages for unknown invocations.
|
* or to display help messages for unknown invocations.
|
||||||
@ -16,6 +17,8 @@ public class CommandHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a command handler.
|
* Create a command handler.
|
||||||
|
*
|
||||||
|
* @param commandService The CommandService instance
|
||||||
*/
|
*/
|
||||||
public CommandHandler(CommandService commandService) {
|
public CommandHandler(CommandService commandService) {
|
||||||
this.commandService = commandService;
|
this.commandService = commandService;
|
||||||
@ -45,6 +48,12 @@ public class CommandHandler {
|
|||||||
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
|
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command for the given command sender.
|
||||||
|
*
|
||||||
|
* @param sender The sender which initiated the command
|
||||||
|
* @param result The mapped result
|
||||||
|
*/
|
||||||
private void executeCommand(CommandSender sender, FoundCommandResult result) {
|
private void executeCommand(CommandSender sender, FoundCommandResult result) {
|
||||||
ExecutableCommand executableCommand = result.getCommandDescription().getExecutableCommand();
|
ExecutableCommand executableCommand = result.getCommandDescription().getExecutableCommand();
|
||||||
List<String> arguments = result.getArguments();
|
List<String> arguments = result.getArguments();
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
package fr.xephi.authme.command;
|
package fr.xephi.authme.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.command.help.HelpProvider;
|
import fr.xephi.authme.command.help.HelpProvider;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
@ -8,9 +12,6 @@ import fr.xephi.authme.output.Messages;
|
|||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
|
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
|
||||||
@ -31,6 +32,7 @@ public class CommandService {
|
|||||||
* @param commandMapper Command mapper
|
* @param commandMapper Command mapper
|
||||||
* @param helpProvider Help provider
|
* @param helpProvider Help provider
|
||||||
* @param messages Messages instance
|
* @param messages Messages instance
|
||||||
|
* @param passwordSecurity The Password Security instance
|
||||||
*/
|
*/
|
||||||
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
|
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
|
||||||
PasswordSecurity passwordSecurity) {
|
PasswordSecurity passwordSecurity) {
|
||||||
@ -51,6 +53,13 @@ public class CommandService {
|
|||||||
messages.send(sender, messageKey);
|
messages.send(sender, messageKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to a player.
|
||||||
|
*
|
||||||
|
* @param sender The command sender to send the message to
|
||||||
|
* @param messageKey The message key to send
|
||||||
|
* @param replacements The replacement arguments for the message key's tags
|
||||||
|
*/
|
||||||
public void send(CommandSender sender, MessageKey messageKey, String... replacements) {
|
public void send(CommandSender sender, MessageKey messageKey, String... replacements) {
|
||||||
messages.send(sender, messageKey, replacements);
|
messages.send(sender, messageKey, replacements);
|
||||||
}
|
}
|
||||||
@ -119,7 +128,7 @@ public class CommandService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the management instance of the plugin.
|
* Return the management instance of the plugin.
|
||||||
*
|
*
|
||||||
* @return The Management instance linked to the AuthMe instance
|
* @return The Management instance linked to the AuthMe instance
|
||||||
*/
|
*/
|
||||||
@ -127,11 +136,22 @@ public class CommandService {
|
|||||||
return authMe.getManagement();
|
return authMe.getManagement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the permissions manager.
|
||||||
|
*
|
||||||
|
* @return the permissions manager
|
||||||
|
*/
|
||||||
public PermissionsManager getPermissionsManager() {
|
public PermissionsManager getPermissionsManager() {
|
||||||
// TODO ljacqu 20151226: Might be nicer to pass the perm manager via constructor
|
// TODO ljacqu 20151226: Might be nicer to pass the perm manager via constructor
|
||||||
return authMe.getPermissionsManager();
|
return authMe.getPermissionsManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a message by its message key.
|
||||||
|
*
|
||||||
|
* @param key The message to retrieve
|
||||||
|
* @return The message
|
||||||
|
*/
|
||||||
public String[] retrieveMessage(MessageKey key) {
|
public String[] retrieveMessage(MessageKey key) {
|
||||||
return messages.retrieve(key);
|
return messages.retrieve(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping
|
* Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping
|
||||||
* as well as erroneous ones, as communicated with {@link FoundResultStatus}.
|
* as well as erroneous ones, as communicated with {@link FoundResultStatus}.
|
||||||
* <p />
|
* <p>
|
||||||
* Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status:
|
* Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore,
|
* <li>{@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore,
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command;
|
package fr.xephi.authme.command;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common base type for player-only commands, handling the verification that the command sender is indeed a player.
|
* Common base type for player-only commands, handling the verification that the command sender is indeed a player.
|
||||||
*/
|
*/
|
||||||
@ -35,7 +35,7 @@ public abstract class PlayerCommand implements ExecutableCommand {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an alternative command (textual representation) that is not restricted to players only.
|
* Return an alternative command (textual representation) that is not restricted to players only.
|
||||||
* Example: "authme register <playerName> <password>"
|
* Example: {@code "authme register <playerName> <password>"}
|
||||||
*
|
*
|
||||||
* @return Alternative command not only for players, or null if not applicable
|
* @return Alternative command not only for players, or null if not applicable
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import com.google.common.cache.LoadingCache;
|
|||||||
import com.google.common.cache.RemovalListener;
|
import com.google.common.cache.RemovalListener;
|
||||||
import com.google.common.cache.RemovalListeners;
|
import com.google.common.cache.RemovalListeners;
|
||||||
import com.google.common.cache.RemovalNotification;
|
import com.google.common.cache.RemovalNotification;
|
||||||
|
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 fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
@ -52,15 +53,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method isAuthAvailable.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isAuthAvailable(String user) {
|
public synchronized boolean isAuthAvailable(String user) {
|
||||||
return getAuth(user) != null;
|
return getAuth(user) != null;
|
||||||
@ -91,15 +83,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return cachedAuths.getUnchecked(user).orNull();
|
return cachedAuths.getUnchecked(user).orNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method saveAuth.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean saveAuth(PlayerAuth auth) {
|
public synchronized boolean saveAuth(PlayerAuth auth) {
|
||||||
boolean result = source.saveAuth(auth);
|
boolean result = source.saveAuth(auth);
|
||||||
@ -109,15 +92,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updatePassword.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
boolean result = source.updatePassword(auth);
|
boolean result = source.updatePassword(auth);
|
||||||
@ -137,15 +111,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSession.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSession(PlayerAuth auth) {
|
public boolean updateSession(PlayerAuth auth) {
|
||||||
boolean result = source.updateSession(auth);
|
boolean result = source.updateSession(auth);
|
||||||
@ -155,47 +120,20 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateQuitLoc.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(final PlayerAuth auth) {
|
public boolean updateQuitLoc(final PlayerAuth auth) {
|
||||||
boolean result = source.updateSession(auth);
|
boolean result = source.updateQuitLoc(auth);
|
||||||
if (result) {
|
if (result) {
|
||||||
cachedAuths.refresh(auth.getNickname());
|
cachedAuths.refresh(auth.getNickname());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getIps.
|
|
||||||
*
|
|
||||||
* @param ip String
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getIps(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getIps(String ip) {
|
public int getIps(String ip) {
|
||||||
return source.getIps(ip);
|
return source.getIps(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method purgeDatabase.
|
|
||||||
*
|
|
||||||
* @param until long
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int purgeDatabase(long until) {
|
public int purgeDatabase(long until) {
|
||||||
int cleared = source.purgeDatabase(until);
|
int cleared = source.purgeDatabase(until);
|
||||||
@ -209,15 +147,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return cleared;
|
return cleared;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method autoPurgeDatabase.
|
|
||||||
*
|
|
||||||
* @param until long
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> autoPurgeDatabase(long until) {
|
public List<String> autoPurgeDatabase(long until) {
|
||||||
List<String> cleared = source.autoPurgeDatabase(until);
|
List<String> cleared = source.autoPurgeDatabase(until);
|
||||||
@ -227,15 +156,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
return cleared;
|
return cleared;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method removeAuth.
|
|
||||||
*
|
|
||||||
* @param name String
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#removeAuth(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean removeAuth(String name) {
|
public synchronized boolean removeAuth(String name) {
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
@ -246,22 +166,17 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method close.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#close()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void close() {
|
public synchronized void close() {
|
||||||
exec.shutdown();
|
try {
|
||||||
|
exec.shutdown();
|
||||||
|
exec.awaitTermination(8, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
ConsoleLogger.writeStackTrace(e);
|
||||||
|
}
|
||||||
source.close();
|
source.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method reload.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#reload()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() { // unused method
|
public void reload() { // unused method
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -273,15 +188,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateEmail.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updateEmail(final PlayerAuth auth) {
|
public synchronized boolean updateEmail(final PlayerAuth auth) {
|
||||||
boolean result = source.updateEmail(auth);
|
boolean result = source.updateEmail(auth);
|
||||||
@ -291,55 +197,21 @@ public class CacheDataSource implements DataSource {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByName.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||||
return source.getAllAuthsByName(auth);
|
return source.getAllAuthsByName(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByIp.
|
|
||||||
*
|
|
||||||
* @param ip String
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<String> getAllAuthsByIp(final String ip) {
|
public synchronized List<String> getAllAuthsByIp(final String ip) {
|
||||||
return source.getAllAuthsByIp(ip);
|
return source.getAllAuthsByIp(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByEmail.
|
|
||||||
*
|
|
||||||
* @param email String
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<String> getAllAuthsByEmail(final String email) {
|
public synchronized List<String> getAllAuthsByEmail(final String email) {
|
||||||
return source.getAllAuthsByEmail(email);
|
return source.getAllAuthsByEmail(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method purgeBanned.
|
|
||||||
*
|
|
||||||
* @param banned List<String>
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#purgeBanned(List)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void purgeBanned(final List<String> banned) {
|
public synchronized void purgeBanned(final List<String> banned) {
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -351,39 +223,16 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getType.
|
|
||||||
*
|
|
||||||
* @return DataSourceType
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public DataSourceType getType() {
|
public DataSourceType getType() {
|
||||||
return source.getType();
|
return source.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method isLogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#isLogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLogged(String user) {
|
public boolean isLogged(String user) {
|
||||||
return PlayerCache.getInstance().isAuthenticated(user);
|
return PlayerCache.getInstance().isAuthenticated(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setLogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#setLogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setLogged(final String user) {
|
public void setLogged(final String user) {
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -394,13 +243,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setUnlogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#setUnlogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setUnlogged(final String user) {
|
public void setUnlogged(final String user) {
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -411,11 +253,6 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method purgeLogged.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#purgeLogged()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void purgeLogged() {
|
public void purgeLogged() {
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -427,26 +264,11 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAccountsRegistered.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getAccountsRegistered() {
|
public int getAccountsRegistered() {
|
||||||
return source.getAccountsRegistered();
|
return source.getAccountsRegistered();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateName.
|
|
||||||
*
|
|
||||||
* @param oldOne String
|
|
||||||
* @param newOne String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#updateName(String, String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void updateName(final String oldOne, final String newOne) {
|
public void updateName(final String oldOne, final String newOne) {
|
||||||
exec.execute(new Runnable() {
|
exec.execute(new Runnable() {
|
||||||
@ -458,25 +280,11 @@ public class CacheDataSource implements DataSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuths.
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getAllAuths()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getAllAuths() {
|
public List<PlayerAuth> getAllAuths() {
|
||||||
return source.getAllAuths();
|
return source.getAllAuths();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getLoggedPlayers.
|
|
||||||
*
|
|
||||||
* @return List
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getLoggedPlayers() {
|
public List<PlayerAuth> getLoggedPlayers() {
|
||||||
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
|
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
|
||||||
|
|||||||
@ -79,7 +79,7 @@ public interface DataSource {
|
|||||||
*
|
*
|
||||||
* @param until long
|
* @param until long
|
||||||
*
|
*
|
||||||
* @return List<String>
|
* @return List of String
|
||||||
*/
|
*/
|
||||||
List<String> autoPurgeDatabase(long until);
|
List<String> autoPurgeDatabase(long until);
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ public interface DataSource {
|
|||||||
*
|
*
|
||||||
* @param auth PlayerAuth
|
* @param auth PlayerAuth
|
||||||
*
|
*
|
||||||
* @return List<String>
|
* @return List of String
|
||||||
*/
|
*/
|
||||||
List<String> getAllAuthsByName(PlayerAuth auth);
|
List<String> getAllAuthsByName(PlayerAuth auth);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ public interface DataSource {
|
|||||||
*
|
*
|
||||||
* @param ip String
|
* @param ip String
|
||||||
*
|
*
|
||||||
* @return List<String> * @throws Exception
|
* @return List of String * @throws Exception
|
||||||
*/
|
*/
|
||||||
List<String> getAllAuthsByIp(String ip);
|
List<String> getAllAuthsByIp(String ip);
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ public interface DataSource {
|
|||||||
*
|
*
|
||||||
* @param email String
|
* @param email String
|
||||||
*
|
*
|
||||||
* @return List<String> * @throws Exception
|
* @return List of String * @throws Exception
|
||||||
*/
|
*/
|
||||||
List<String> getAllAuthsByEmail(String email);
|
List<String> getAllAuthsByEmail(String email);
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ public interface DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method purgeBanned.
|
* Method purgeBanned.
|
||||||
*
|
*
|
||||||
* @param banned List<String>
|
* @param banned List of String
|
||||||
*/
|
*/
|
||||||
void purgeBanned(List<String> banned);
|
void purgeBanned(List<String> banned);
|
||||||
|
|
||||||
@ -207,14 +207,14 @@ public interface DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method getAllAuths.
|
* Method getAllAuths.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth>
|
* @return List of PlayerAuth
|
||||||
*/
|
*/
|
||||||
List<PlayerAuth> getAllAuths();
|
List<PlayerAuth> getAllAuths();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method getLoggedPlayers.
|
* Method getLoggedPlayers.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth>
|
* @return List of PlayerAuth
|
||||||
*/
|
*/
|
||||||
List<PlayerAuth> getLoggedPlayers();
|
List<PlayerAuth> getLoggedPlayers();
|
||||||
|
|
||||||
|
|||||||
@ -406,7 +406,7 @@ public class FlatFile implements DataSource {
|
|||||||
*
|
*
|
||||||
* @param until long
|
* @param until long
|
||||||
*
|
*
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
|
* @return List of String * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> autoPurgeDatabase(long until) {
|
public List<String> autoPurgeDatabase(long until) {
|
||||||
@ -622,7 +622,7 @@ public class FlatFile implements DataSource {
|
|||||||
*
|
*
|
||||||
* @param auth PlayerAuth
|
* @param auth PlayerAuth
|
||||||
*
|
*
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
|
* @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||||
@ -659,7 +659,7 @@ public class FlatFile implements DataSource {
|
|||||||
*
|
*
|
||||||
* @param ip String
|
* @param ip String
|
||||||
*
|
*
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
|
* @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByIp(String ip) {
|
public List<String> getAllAuthsByIp(String ip) {
|
||||||
@ -696,7 +696,7 @@ public class FlatFile implements DataSource {
|
|||||||
*
|
*
|
||||||
* @param email String
|
* @param email String
|
||||||
*
|
*
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
|
* @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByEmail(String email) {
|
public List<String> getAllAuthsByEmail(String email) {
|
||||||
@ -731,7 +731,7 @@ public class FlatFile implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method purgeBanned.
|
* Method purgeBanned.
|
||||||
*
|
*
|
||||||
* @param banned List<String>
|
* @param banned List of String
|
||||||
*
|
*
|
||||||
* @see fr.xephi.authme.datasource.DataSource#purgeBanned(List)
|
* @see fr.xephi.authme.datasource.DataSource#purgeBanned(List)
|
||||||
*/
|
*/
|
||||||
@ -876,7 +876,7 @@ public class FlatFile implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method getAllAuths.
|
* Method getAllAuths.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth> * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
|
* @return List of PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getAllAuths() {
|
public List<PlayerAuth> getAllAuths() {
|
||||||
@ -928,7 +928,7 @@ public class FlatFile implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Method getLoggedPlayers.
|
* Method getLoggedPlayers.
|
||||||
*
|
*
|
||||||
* @return List<PlayerAuth> * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
|
* @return List of PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getLoggedPlayers() {
|
public List<PlayerAuth> getLoggedPlayers() {
|
||||||
|
|||||||
@ -1,11 +1,5 @@
|
|||||||
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;
|
||||||
@ -15,6 +9,12 @@ 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 {
|
||||||
@ -40,7 +40,8 @@ public class SQLite implements DataSource {
|
|||||||
/**
|
/**
|
||||||
* Constructor for SQLite.
|
* Constructor for SQLite.
|
||||||
*
|
*
|
||||||
* @throws ClassNotFoundException * @throws SQLException
|
* @throws ClassNotFoundException Exception
|
||||||
|
* @throws SQLException Exception
|
||||||
*/
|
*/
|
||||||
public SQLite() throws ClassNotFoundException, SQLException {
|
public SQLite() throws ClassNotFoundException, SQLException {
|
||||||
this.database = Settings.getMySQLDatabase;
|
this.database = Settings.getMySQLDatabase;
|
||||||
@ -69,11 +70,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method connect.
|
|
||||||
*
|
|
||||||
* @throws ClassNotFoundException * @throws SQLException
|
|
||||||
*/
|
|
||||||
private synchronized void connect() throws ClassNotFoundException, SQLException {
|
private synchronized void connect() throws ClassNotFoundException, SQLException {
|
||||||
Class.forName("org.sqlite.JDBC");
|
Class.forName("org.sqlite.JDBC");
|
||||||
ConsoleLogger.info("SQLite driver loaded");
|
ConsoleLogger.info("SQLite driver loaded");
|
||||||
@ -81,11 +77,6 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setup.
|
|
||||||
*
|
|
||||||
* @throws SQLException
|
|
||||||
*/
|
|
||||||
private synchronized void setup() throws SQLException {
|
private synchronized void setup() throws SQLException {
|
||||||
Statement st = null;
|
Statement st = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -147,13 +138,6 @@ public class SQLite implements DataSource {
|
|||||||
ConsoleLogger.info("SQLite Setup finished");
|
ConsoleLogger.info("SQLite Setup finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method isAuthAvailable.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isAuthAvailable(String user) {
|
public synchronized boolean isAuthAvailable(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -224,13 +208,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method saveAuth.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean saveAuth(PlayerAuth auth) {
|
public synchronized boolean saveAuth(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -270,13 +247,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updatePassword.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean updatePassword(PlayerAuth auth) {
|
public synchronized boolean updatePassword(PlayerAuth auth) {
|
||||||
return updatePassword(auth.getNickname(), auth.getPassword());
|
return updatePassword(auth.getNickname(), auth.getPassword());
|
||||||
@ -309,13 +279,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateSession.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSession(PlayerAuth auth) {
|
public boolean updateSession(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -335,13 +298,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method purgeDatabase.
|
|
||||||
*
|
|
||||||
* @param until long
|
|
||||||
*
|
|
||||||
* @return int * @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int purgeDatabase(long until) {
|
public int purgeDatabase(long until) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -358,13 +314,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method autoPurgeDatabase.
|
|
||||||
*
|
|
||||||
* @param until long
|
|
||||||
*
|
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> autoPurgeDatabase(long until) {
|
public List<String> autoPurgeDatabase(long until) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -387,13 +336,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method removeAuth.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#removeAuth(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean removeAuth(String user) {
|
public synchronized boolean removeAuth(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -410,13 +352,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateQuitLoc.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -437,13 +372,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getIps.
|
|
||||||
*
|
|
||||||
* @param ip String
|
|
||||||
*
|
|
||||||
* @return int * @see fr.xephi.authme.datasource.DataSource#getIps(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getIps(String ip) {
|
public int getIps(String ip) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -467,13 +395,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateEmail.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateEmail(PlayerAuth auth) {
|
public boolean updateEmail(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -491,11 +412,6 @@ public class SQLite implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method close.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#close()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void close() {
|
public synchronized void close() {
|
||||||
try {
|
try {
|
||||||
@ -505,20 +421,10 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method reload.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#reload()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method close.
|
|
||||||
*
|
|
||||||
* @param st Statement
|
|
||||||
*/
|
|
||||||
private void close(Statement st) {
|
private void close(Statement st) {
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
try {
|
try {
|
||||||
@ -529,11 +435,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method close.
|
|
||||||
*
|
|
||||||
* @param rs ResultSet
|
|
||||||
*/
|
|
||||||
private void close(ResultSet rs) {
|
private void close(ResultSet rs) {
|
||||||
if (rs != null) {
|
if (rs != null) {
|
||||||
try {
|
try {
|
||||||
@ -544,13 +445,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByName.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*
|
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -575,13 +469,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByIp.
|
|
||||||
*
|
|
||||||
* @param ip String
|
|
||||||
*
|
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByIp(String ip) {
|
public List<String> getAllAuthsByIp(String ip) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -606,13 +493,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuthsByEmail.
|
|
||||||
*
|
|
||||||
* @param email String
|
|
||||||
*
|
|
||||||
* @return List<String> * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByEmail(String email) {
|
public List<String> getAllAuthsByEmail(String email) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -653,23 +533,11 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getType.
|
|
||||||
*
|
|
||||||
* @return DataSourceType * @see fr.xephi.authme.datasource.DataSource#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public DataSourceType getType() {
|
public DataSourceType getType() {
|
||||||
return DataSourceType.SQLITE;
|
return DataSourceType.SQLITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method isLogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @return boolean * @see fr.xephi.authme.datasource.DataSource#isLogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLogged(String user) {
|
public boolean isLogged(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -690,13 +558,6 @@ public class SQLite implements DataSource {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setLogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#setLogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setLogged(String user) {
|
public void setLogged(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -712,13 +573,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method setUnlogged.
|
|
||||||
*
|
|
||||||
* @param user String
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#setUnlogged(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setUnlogged(String user) {
|
public void setUnlogged(String user) {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -735,11 +589,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method purgeLogged.
|
|
||||||
*
|
|
||||||
* @see fr.xephi.authme.datasource.DataSource#purgeLogged()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void purgeLogged() {
|
public void purgeLogged() {
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
@ -755,11 +604,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAccountsRegistered.
|
|
||||||
*
|
|
||||||
* @return int * @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int getAccountsRegistered() {
|
public int getAccountsRegistered() {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -795,11 +639,6 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getAllAuths.
|
|
||||||
*
|
|
||||||
* @return List<PlayerAuth>
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getAllAuths() {
|
public List<PlayerAuth> getAllAuths() {
|
||||||
List<PlayerAuth> auths = new ArrayList<>();
|
List<PlayerAuth> auths = new ArrayList<>();
|
||||||
@ -821,11 +660,6 @@ public class SQLite implements DataSource {
|
|||||||
return auths;
|
return auths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getLoggedPlayers.
|
|
||||||
*
|
|
||||||
* @return List<PlayerAuth>
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<PlayerAuth> getLoggedPlayers() {
|
public List<PlayerAuth> getLoggedPlayers() {
|
||||||
List<PlayerAuth> auths = new ArrayList<>();
|
List<PlayerAuth> auths = new ArrayList<>();
|
||||||
|
|||||||
@ -193,7 +193,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.isForceSurvivalModeEnabled
|
if (Settings.isForceSurvivalModeEnabled
|
||||||
&& !player.hasPermission(PlayerPermission.BYPASS_FORCE_SURVIVAL.getNode())) {
|
&& !player.hasPermission(PlayerPermission.BYPASS_FORCE_SURVIVAL.getNode())) {
|
||||||
player.setGameMode(GameMode.SURVIVAL);
|
player.setGameMode(GameMode.SURVIVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,9 +206,6 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
joinMessage.put(name, joinMsg);
|
joinMessage.put(name, joinMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.checkVeryGames)
|
|
||||||
plugin.getVerygamesIp(player);
|
|
||||||
|
|
||||||
// Shedule login task so works after the prelogin
|
// Shedule login task so works after the prelogin
|
||||||
// (Fix found by Koolaid5000)
|
// (Fix found by Koolaid5000)
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||||
@ -222,21 +219,24 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onPreLogin(AsyncPlayerPreLoginEvent event) {
|
public void onPreLogin(AsyncPlayerPreLoginEvent event) {
|
||||||
PlayerAuth auth = plugin.getDataSource().getAuth(event.getName());
|
PlayerAuth auth = plugin.getDataSource().getAuth(event.getName());
|
||||||
if (auth != null && auth.getRealName() != null && !auth.getRealName().isEmpty() &&
|
if (Settings.preventOtherCase && auth != null && auth.getRealName() != null) {
|
||||||
!auth.getRealName().equals("Player") && !auth.getRealName().equals(event.getName())) {
|
String realName = auth.getRealName();
|
||||||
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
if (!realName.isEmpty() && !realName.equals("Player") && !realName.equals(event.getName())) {
|
||||||
event.setKickMessage("You should join using username: " + ChatColor.AQUA + auth.getRealName() +
|
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||||
ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName()); // TODO: write a better message
|
// TODO: Add a message like : MessageKey.INVALID_NAME_CASE
|
||||||
return;
|
event.setKickMessage("You should join using username: " + ChatColor.AQUA + realName +
|
||||||
}
|
ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName());
|
||||||
|
return;
|
||||||
if (auth != null && auth.getRealName().equals("Player")) {
|
}
|
||||||
auth.setRealName(event.getName());
|
if (realName.isEmpty() || realName.equals("Player")) {
|
||||||
plugin.getDataSource().saveAuth(auth);
|
auth.setRealName(event.getName());
|
||||||
|
plugin.getDataSource().saveAuth(auth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String playerIP = event.getAddress().getHostAddress();
|
||||||
if (auth == null && Settings.enableProtection) {
|
if (auth == null && Settings.enableProtection) {
|
||||||
String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress());
|
String countryCode = GeoLiteAPI.getCountryCode(playerIP);
|
||||||
if (!Settings.countriesBlacklist.isEmpty() && Settings.countriesBlacklist.contains(countryCode)) {
|
if (!Settings.countriesBlacklist.isEmpty() && Settings.countriesBlacklist.contains(countryCode)) {
|
||||||
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||||
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
|
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
|
||||||
@ -274,21 +274,26 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
// Get the permissions manager
|
// Get the permissions manager
|
||||||
PermissionsManager permsMan = plugin.getPermissionsManager();
|
PermissionsManager permsMan = plugin.getPermissionsManager();
|
||||||
|
|
||||||
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL
|
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL) {
|
||||||
&& permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
|
if (permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
|
||||||
int playersOnline = Utils.getOnlinePlayers().size();
|
int playersOnline = Utils.getOnlinePlayers().size();
|
||||||
if (playersOnline > plugin.getServer().getMaxPlayers()) {
|
if (playersOnline > plugin.getServer().getMaxPlayers()) {
|
||||||
event.allow();
|
|
||||||
} else {
|
|
||||||
Player pl = plugin.generateKickPlayer(Utils.getOnlinePlayers());
|
|
||||||
if (pl != null) {
|
|
||||||
pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
|
|
||||||
event.allow();
|
event.allow();
|
||||||
} else {
|
} else {
|
||||||
ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full");
|
Player pl = plugin.generateKickPlayer(Utils.getOnlinePlayers());
|
||||||
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
|
if (pl != null) {
|
||||||
event.setResult(PlayerLoginEvent.Result.KICK_FULL);
|
pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
|
||||||
|
event.allow();
|
||||||
|
} else {
|
||||||
|
ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full");
|
||||||
|
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
|
||||||
|
event.setResult(PlayerLoginEvent.Result.KICK_FULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
|
||||||
|
event.setResult(PlayerLoginEvent.Result.KICK_FULL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,12 +301,6 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && !permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
|
|
||||||
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
|
|
||||||
event.setResult(PlayerLoginEvent.Result.KICK_FULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
boolean isAuthAvailable = plugin.getDataSource().isAuthAvailable(name);
|
boolean isAuthAvailable = plugin.getDataSource().isAuthAvailable(name);
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
package fr.xephi.authme.listener;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
|
|
||||||
public class AuthMeServerStop extends Thread {
|
|
||||||
|
|
||||||
private AuthMe plugin;
|
|
||||||
|
|
||||||
public AuthMeServerStop(AuthMe plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
// TODO: add a MessageKey
|
|
||||||
if (Settings.kickPlayersBeforeStopping) {
|
|
||||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (Player p : plugin.getServer().getOnlinePlayers()) {
|
|
||||||
p.kickPlayer("Server is restarting");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -25,7 +25,11 @@ public enum DefaultPermission {
|
|||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the textual representation. */
|
/**
|
||||||
|
* Return the textual representation.
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
package fr.xephi.authme.permission;
|
package fr.xephi.authme.permission;
|
||||||
|
|
||||||
import de.bananaco.bpermissions.api.ApiLayer;
|
import java.util.ArrayList;
|
||||||
import de.bananaco.bpermissions.api.CalculableType;
|
import java.util.Arrays;
|
||||||
import fr.xephi.authme.command.CommandDescription;
|
import java.util.List;
|
||||||
import fr.xephi.authme.util.CollectionUtils;
|
import java.util.Map;
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.anjocaido.groupmanager.GroupManager;
|
import org.anjocaido.groupmanager.GroupManager;
|
||||||
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
|
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -17,24 +18,25 @@ import org.bukkit.plugin.Plugin;
|
|||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
|
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
|
||||||
|
|
||||||
|
import de.bananaco.bpermissions.api.ApiLayer;
|
||||||
|
import de.bananaco.bpermissions.api.CalculableType;
|
||||||
|
import fr.xephi.authme.command.CommandDescription;
|
||||||
|
import fr.xephi.authme.util.CollectionUtils;
|
||||||
|
import net.milkbowl.vault.permission.Permission;
|
||||||
import ru.tehkode.permissions.PermissionManager;
|
import ru.tehkode.permissions.PermissionManager;
|
||||||
import ru.tehkode.permissions.PermissionUser;
|
import ru.tehkode.permissions.PermissionUser;
|
||||||
import ru.tehkode.permissions.bukkit.PermissionsEx;
|
import ru.tehkode.permissions.bukkit.PermissionsEx;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
* PermissionsManager.
|
* PermissionsManager.
|
||||||
* <p/>
|
* </p><p>
|
||||||
* A permissions manager, to manage and use various permissions systems.
|
* A permissions manager, to manage and use various permissions systems.
|
||||||
* This manager supports dynamic plugin hooking and various other features.
|
* This manager supports dynamic plugin hooking and various other features.
|
||||||
* <p/>
|
* </p><p>
|
||||||
* Written by Tim Visée.
|
* Written by Tim Visée.
|
||||||
*
|
* </p>
|
||||||
* @author Tim Visée, http://timvisee.com
|
* @author Tim Visée, http://timvisee.com
|
||||||
* @version 0.2.1
|
* @version 0.2.1
|
||||||
*/
|
*/
|
||||||
@ -296,8 +298,8 @@ public class PermissionsManager implements PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player player = (Player) sender;
|
Player player = (Player) sender;
|
||||||
return hasPermission(player, permissionNode.getNode(), def)
|
return hasPermission(player, permissionNode.getNode(), def);
|
||||||
|| hasPermission(player, permissionNode.getWildcardNode().getNode(), def);
|
// || hasPermission(player, permissionNode.getWildcardNode().getNode(), def);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPermission(Player player, Iterable<PermissionNode> nodes, boolean def) {
|
public boolean hasPermission(Player player, Iterable<PermissionNode> nodes, boolean def) {
|
||||||
|
|||||||
@ -49,6 +49,10 @@ public class AsynchronousJoin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void process() {
|
public void process() {
|
||||||
|
if (Settings.checkVeryGames) {
|
||||||
|
plugin.getVerygamesIp(player);
|
||||||
|
}
|
||||||
|
|
||||||
if (Utils.isUnrestricted(player)) {
|
if (Utils.isUnrestricted(player)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -58,6 +62,8 @@ public class AsynchronousJoin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String ip = plugin.getIP(player);
|
final String ip = plugin.getIP(player);
|
||||||
|
|
||||||
|
|
||||||
if (Settings.isAllowRestrictedIp && !Settings.getRestrictedIp(name, ip, player.getAddress().getHostName())) {
|
if (Settings.isAllowRestrictedIp && !Settings.getRestrictedIp(name, ip, player.getAddress().getHostName())) {
|
||||||
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
|
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
|
|
||||||
@ -110,7 +116,6 @@ public class AsynchronousJoin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
placePlayerSafely(player, spawnLoc);
|
placePlayerSafely(player, spawnLoc);
|
||||||
LimboCache.getInstance().updateLimboPlayer(player);
|
LimboCache.getInstance().updateLimboPlayer(player);
|
||||||
|
|
||||||
@ -126,6 +131,22 @@ public class AsynchronousJoin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.isSessionsEnabled && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) {
|
||||||
|
if (plugin.sessions.containsKey(name)) {
|
||||||
|
plugin.sessions.get(name).cancel();
|
||||||
|
plugin.sessions.remove(name);
|
||||||
|
}
|
||||||
|
PlayerAuth auth = database.getAuth(name);
|
||||||
|
database.setUnlogged(name);
|
||||||
|
PlayerCache.getInstance().removePlayer(name);
|
||||||
|
if (auth != null && auth.getIp().equals(ip)) {
|
||||||
|
m.send(player, MessageKey.SESSION_RECONNECTION);
|
||||||
|
plugin.getManagement().performLogin(player, "dontneed", true);
|
||||||
|
return;
|
||||||
|
} else if (Settings.sessionExpireOnIpChange) {
|
||||||
|
m.send(player, MessageKey.SESSION_EXPIRED);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!Settings.unRegisteredGroup.isEmpty()) {
|
if (!Settings.unRegisteredGroup.isEmpty()) {
|
||||||
Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
|
Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
|
||||||
@ -179,7 +200,7 @@ public class AsynchronousJoin {
|
|||||||
if (Settings.applyBlindEffect) {
|
if (Settings.applyBlindEffect) {
|
||||||
int blindTimeOut;
|
int blindTimeOut;
|
||||||
// Allow infinite blindness effect
|
// Allow infinite blindness effect
|
||||||
if(timeOut <= 0) {
|
if (timeOut <= 0) {
|
||||||
blindTimeOut = 99999;
|
blindTimeOut = 99999;
|
||||||
} else {
|
} else {
|
||||||
blindTimeOut = timeOut;
|
blindTimeOut = timeOut;
|
||||||
@ -196,23 +217,6 @@ public class AsynchronousJoin {
|
|||||||
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
|
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.isSessionsEnabled && isAuthAvailable && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) {
|
|
||||||
if (plugin.sessions.containsKey(name)) {
|
|
||||||
plugin.sessions.get(name).cancel();
|
|
||||||
plugin.sessions.remove(name);
|
|
||||||
}
|
|
||||||
PlayerAuth auth = database.getAuth(name);
|
|
||||||
database.setUnlogged(name);
|
|
||||||
PlayerCache.getInstance().removePlayer(name);
|
|
||||||
if (auth != null && auth.getIp().equals(ip)) {
|
|
||||||
m.send(player, MessageKey.SESSION_RECONNECTION);
|
|
||||||
plugin.getManagement().performLogin(player, "dontneed", true);
|
|
||||||
return;
|
|
||||||
} else if (Settings.sessionExpireOnIpChange) {
|
|
||||||
m.send(player, MessageKey.SESSION_EXPIRED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] msg;
|
String[] msg;
|
||||||
if (isAuthAvailable) {
|
if (isAuthAvailable) {
|
||||||
msg = m.retrieve(MessageKey.LOGIN_MESSAGE);
|
msg = m.retrieve(MessageKey.LOGIN_MESSAGE);
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class AsynchronousLogin {
|
|||||||
private final AuthMe plugin;
|
private final AuthMe plugin;
|
||||||
private final DataSource database;
|
private final DataSource database;
|
||||||
private final Messages m;
|
private final Messages m;
|
||||||
|
private final String ip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for AsynchronousLogin.
|
* Constructor for AsynchronousLogin.
|
||||||
@ -52,10 +53,7 @@ public class AsynchronousLogin {
|
|||||||
this.forceLogin = forceLogin;
|
this.forceLogin = forceLogin;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.database = data;
|
this.database = data;
|
||||||
}
|
this.ip = plugin.getIP(player);
|
||||||
|
|
||||||
protected String getIP() {
|
|
||||||
return plugin.getIP(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean needsCaptcha() {
|
protected boolean needsCaptcha() {
|
||||||
@ -87,7 +85,9 @@ public class AsynchronousLogin {
|
|||||||
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!database.isAuthAvailable(name)) {
|
|
||||||
|
PlayerAuth pAuth = database.getAuth(name);
|
||||||
|
if (pAuth == null) {
|
||||||
m.send(player, MessageKey.USER_NOT_REGISTERED);
|
m.send(player, MessageKey.USER_NOT_REGISTERED);
|
||||||
if (LimboCache.getInstance().hasLimboPlayer(name)) {
|
if (LimboCache.getInstance().hasLimboPlayer(name)) {
|
||||||
LimboCache.getInstance().getLimboPlayer(name).getMessageTaskId().cancel();
|
LimboCache.getInstance().getLimboPlayer(name).getMessageTaskId().cancel();
|
||||||
@ -97,43 +97,45 @@ public class AsynchronousLogin {
|
|||||||
} else {
|
} else {
|
||||||
msg = m.retrieve(MessageKey.REGISTER_MESSAGE);
|
msg = m.retrieve(MessageKey.REGISTER_MESSAGE);
|
||||||
}
|
}
|
||||||
BukkitTask msgT = Bukkit.getScheduler().runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, Settings.getWarnMessageInterval));
|
BukkitTask msgT = Bukkit.getScheduler().runTaskAsynchronously(plugin,
|
||||||
|
new MessageTask(plugin, name, msg, Settings.getWarnMessageInterval));
|
||||||
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
|
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (Settings.getMaxLoginPerIp > 0 && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS) && !getIP().equalsIgnoreCase("127.0.0.1") && !getIP().equalsIgnoreCase("localhost")) {
|
|
||||||
if (plugin.isLoggedIp(name, getIP())) {
|
|
||||||
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PlayerAuth pAuth = database.getAuth(name);
|
|
||||||
if (pAuth == null) {
|
|
||||||
m.send(player, MessageKey.USER_NOT_REGISTERED);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!Settings.getMySQLColumnGroup.isEmpty() && pAuth.getGroupId() == Settings.getNonActivatedGroup) {
|
if (!Settings.getMySQLColumnGroup.isEmpty() && pAuth.getGroupId() == Settings.getNonActivatedGroup) {
|
||||||
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.preventOtherCase && !player.getName().equals(pAuth.getRealName())) {
|
if (Settings.getMaxLoginPerIp > 0
|
||||||
// TODO: Add a message like : MessageKey.INVALID_NAME_CASE
|
&& !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS)
|
||||||
m.send(player, MessageKey.USERNAME_ALREADY_ONLINE_ERROR);
|
&& !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) {
|
||||||
return null;
|
if (plugin.isLoggedIp(name, ip)) {
|
||||||
|
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthMeAsyncPreLoginEvent event = new AuthMeAsyncPreLoginEvent(player);
|
AuthMeAsyncPreLoginEvent event = new AuthMeAsyncPreLoginEvent(player);
|
||||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||||
if (!event.canLogin())
|
if (!event.canLogin()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return pAuth;
|
return pAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process() {
|
public void process() {
|
||||||
PlayerAuth pAuth = preAuth();
|
PlayerAuth pAuth = preAuth();
|
||||||
if (pAuth == null || needsCaptcha())
|
if (pAuth == null || needsCaptcha()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pAuth.getIp().equals("127.0.0.1") && !pAuth.getIp().equals(ip)) {
|
||||||
|
pAuth.setIp(ip);
|
||||||
|
database.saveAuth(pAuth);
|
||||||
|
}
|
||||||
|
|
||||||
String email = pAuth.getEmail();
|
String email = pAuth.getEmail();
|
||||||
boolean passwordVerified = forceLogin || plugin.getPasswordSecurity()
|
boolean passwordVerified = forceLogin || plugin.getPasswordSecurity()
|
||||||
@ -143,7 +145,7 @@ public class AsynchronousLogin {
|
|||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.realName(realName)
|
.realName(realName)
|
||||||
.ip(getIP())
|
.ip(ip)
|
||||||
.lastLogin(new Date().getTime())
|
.lastLogin(new Date().getTime())
|
||||||
.email(email)
|
.email(email)
|
||||||
.password(pAuth.getPassword())
|
.password(pAuth.getPassword())
|
||||||
@ -184,14 +186,16 @@ public class AsynchronousLogin {
|
|||||||
// task, we schedule it in the end
|
// task, we schedule it in the end
|
||||||
// so that we can be sure, and have not to care if it might be
|
// so that we can be sure, and have not to care if it might be
|
||||||
// processed in other order.
|
// processed in other order.
|
||||||
ProcessSyncronousPlayerLogin syncronousPlayerLogin = new ProcessSyncronousPlayerLogin(player, plugin, database);
|
ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(player, plugin, database);
|
||||||
if (syncronousPlayerLogin.getLimbo() != null) {
|
if (syncPlayerLogin.getLimbo() != null) {
|
||||||
if (syncronousPlayerLogin.getLimbo().getTimeoutTaskId() != null)
|
if (syncPlayerLogin.getLimbo().getTimeoutTaskId() != null) {
|
||||||
syncronousPlayerLogin.getLimbo().getTimeoutTaskId().cancel();
|
syncPlayerLogin.getLimbo().getTimeoutTaskId().cancel();
|
||||||
if (syncronousPlayerLogin.getLimbo().getMessageTaskId() != null)
|
}
|
||||||
syncronousPlayerLogin.getLimbo().getMessageTaskId().cancel();
|
if (syncPlayerLogin.getLimbo().getMessageTaskId() != null) {
|
||||||
|
syncPlayerLogin.getLimbo().getMessageTaskId().cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncronousPlayerLogin);
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncPlayerLogin);
|
||||||
} else if (player.isOnline()) {
|
} else if (player.isOnline()) {
|
||||||
if (!Settings.noConsoleSpam)
|
if (!Settings.noConsoleSpam)
|
||||||
ConsoleLogger.info(realName + " used the wrong password");
|
ConsoleLogger.info(realName + " used the wrong password");
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import fr.xephi.authme.util.Utils.GroupType;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public class ProcessSyncronousPlayerLogin implements Runnable {
|
public class ProcessSyncPlayerLogin implements Runnable {
|
||||||
|
|
||||||
private final LimboPlayer limbo;
|
private final LimboPlayer limbo;
|
||||||
private final Player player;
|
private final Player player;
|
||||||
@ -38,14 +38,14 @@ public class ProcessSyncronousPlayerLogin implements Runnable {
|
|||||||
private final JsonCache playerCache;
|
private final JsonCache playerCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for ProcessSyncronousPlayerLogin.
|
* Constructor for ProcessSyncPlayerLogin.
|
||||||
*
|
*
|
||||||
* @param player Player
|
* @param player Player
|
||||||
* @param plugin AuthMe
|
* @param plugin AuthMe
|
||||||
* @param data DataSource
|
* @param data DataSource
|
||||||
*/
|
*/
|
||||||
public ProcessSyncronousPlayerLogin(Player player, AuthMe plugin,
|
public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
|
||||||
DataSource data) {
|
DataSource data) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.database = data;
|
this.database = data;
|
||||||
this.pm = plugin.getServer().getPluginManager();
|
this.pm = plugin.getServer().getPluginManager();
|
||||||
@ -93,6 +93,7 @@ public class AsynchronousQuit {
|
|||||||
database.setUnlogged(name);
|
database.setUnlogged(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin.realIp.remove(name);
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,8 @@ package fr.xephi.authme.security;
|
|||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of hash algorithms supported by AuthMe. The implementing class must define a public
|
* The list of hash algorithms supported by AuthMe. The linked {@link EncryptionMethod} implementation
|
||||||
* constructor which takes either no arguments, or a DataSource object (when the salt is stored
|
* must be able to be instantiated with the default constructor.
|
||||||
* separately, writes to the database are necessary).
|
|
||||||
*/
|
*/
|
||||||
public enum HashAlgorithm {
|
public enum HashAlgorithm {
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ package fr.xephi.authme.security.crypts;
|
|||||||
|
|
||||||
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;
|
||||||
@ -108,7 +109,6 @@ public class BCRYPT implements EncryptionMethod {
|
|||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if the length is invalid
|
* @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 {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
|
|||||||
@ -10,8 +10,6 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
@Recommendation(Usage.DO_NOT_USE)
|
|
||||||
@HasSalt(SaltType.USERNAME)
|
|
||||||
public class CRAZYCRYPT1 extends UsernameSaltMethod {
|
public class CRAZYCRYPT1 extends UsernameSaltMethod {
|
||||||
|
|
||||||
private static final char[] CRYPTCHARS =
|
private static final char[] CRYPTCHARS =
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
|||||||
|
|
||||||
import static fr.xephi.authme.security.HashUtils.md5;
|
import static fr.xephi.authme.security.HashUtils.md5;
|
||||||
|
|
||||||
@Recommendation(Usage.DO_NOT_USE)
|
@Recommendation(Usage.ACCEPTABLE)
|
||||||
@HasSalt(value = SaltType.TEXT, length = 5)
|
@HasSalt(value = SaltType.TEXT, length = 5)
|
||||||
public class IPB3 extends SeparateSaltMethod {
|
public class IPB3 extends SeparateSaltMethod {
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
package fr.xephi.authme.security.crypts;
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
import fr.xephi.authme.security.RandomString;
|
import fr.xephi.authme.security.RandomString;
|
||||||
|
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
|
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
import static fr.xephi.authme.security.HashUtils.md5;
|
import static fr.xephi.authme.security.HashUtils.md5;
|
||||||
|
|
||||||
|
@Recommendation(Usage.ACCEPTABLE)
|
||||||
|
@HasSalt(value = SaltType.TEXT, length = 8)
|
||||||
public class MYBB extends SeparateSaltMethod {
|
public class MYBB extends SeparateSaltMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
package fr.xephi.authme.security.crypts;
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
import fr.xephi.authme.security.RandomString;
|
import fr.xephi.authme.security.RandomString;
|
||||||
|
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
|
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
import static fr.xephi.authme.security.HashUtils.sha1;
|
import static fr.xephi.authme.security.HashUtils.sha1;
|
||||||
|
|
||||||
|
@Recommendation(Usage.ACCEPTABLE)
|
||||||
|
@HasSalt(value = SaltType.TEXT, length = 40)
|
||||||
public class WBB3 extends SeparateSaltMethod {
|
public class WBB3 extends SeparateSaltMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -241,8 +241,9 @@ public class WHIRLPOOL extends UnsaltedMethod {
|
|||||||
*
|
*
|
||||||
* @param source plaintext data to hash.
|
* @param source plaintext data to hash.
|
||||||
* @param sourceBits how many bits of plaintext to process.
|
* @param sourceBits how many bits of plaintext to process.
|
||||||
* <p/>
|
* <p>
|
||||||
* This method maintains the invariant: bufferBits < 512
|
* This method maintains the invariant: bufferBits < 512
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void NESSIEadd(byte[] source, long sourceBits) {
|
public void NESSIEadd(byte[] source, long sourceBits) {
|
||||||
/*
|
/*
|
||||||
@ -322,10 +323,12 @@ public class WHIRLPOOL extends UnsaltedMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>
|
||||||
* Get the hash value from the hashing state.
|
* Get the hash value from the hashing state.
|
||||||
* <p/>
|
* </p>
|
||||||
* This method uses the invariant: bufferBits < 512
|
* <p>
|
||||||
*
|
* This method uses the invariant: bufferBits < 512
|
||||||
|
* </p>
|
||||||
* @param digest byte[]
|
* @param digest byte[]
|
||||||
*/
|
*/
|
||||||
public void NESSIEfinalize(byte[] digest) {
|
public void NESSIEfinalize(byte[] digest) {
|
||||||
@ -367,7 +370,7 @@ public class WHIRLPOOL extends UnsaltedMethod {
|
|||||||
* Delivers string input data to the hashing algorithm.
|
* Delivers string input data to the hashing algorithm.
|
||||||
*
|
*
|
||||||
* @param source plaintext data to hash (ASCII text string).
|
* @param source plaintext data to hash (ASCII text string).
|
||||||
* This method maintains the invariant: bufferBits < 512
|
* This method maintains the invariant: bufferBits < 512
|
||||||
*/
|
*/
|
||||||
public void NESSIEadd(String source) {
|
public void NESSIEadd(String source) {
|
||||||
if (source.length() > 0) {
|
if (source.length() > 0) {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Denotes an encryption algorithm that is restricted to the ASCII charset.
|
* Denotes a hashing algorithm that is restricted to the ASCII charset.
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@ -13,10 +13,18 @@ import java.lang.annotation.Target;
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface HasSalt {
|
public @interface HasSalt {
|
||||||
|
|
||||||
/** The type of the salt. */
|
/**
|
||||||
|
* The type of the salt.
|
||||||
|
*
|
||||||
|
* @return The salt type
|
||||||
|
*/
|
||||||
SaltType value();
|
SaltType value();
|
||||||
|
|
||||||
/** For text salts, the length of the salt. */
|
/**
|
||||||
|
* For text salts, the length of the salt.
|
||||||
|
*
|
||||||
|
* @return The length of the salt the algorithm uses, or 0 if not defined or not applicable.
|
||||||
|
*/
|
||||||
int length() default 0;
|
int length() default 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,19 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to mark a hash algorithm with the usage recommendation, see {@link Usage}.
|
* Annotation to mark a hash algorithm with the usage recommendation.
|
||||||
|
*
|
||||||
|
* @see Usage
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Recommendation {
|
public @interface Recommendation {
|
||||||
|
|
||||||
/** The recommendation for using the hash algorithm. */
|
/**
|
||||||
|
* The recommendation for using the hash algorithm.
|
||||||
|
*
|
||||||
|
* @return The recommended usage
|
||||||
|
*/
|
||||||
Usage value();
|
Usage value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ public enum SaltType {
|
|||||||
/** Random, newly generated text. */
|
/** Random, newly generated text. */
|
||||||
TEXT,
|
TEXT,
|
||||||
|
|
||||||
/** Salt is based on the username, including variations and repetitions. */
|
/** Salt is based on the username, including variations and repetitions thereof. */
|
||||||
USERNAME,
|
USERNAME,
|
||||||
|
|
||||||
/** No salt. */
|
/** No salt. */
|
||||||
|
|||||||
@ -2,6 +2,12 @@ package fr.xephi.authme.security.crypts.description;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage recommendation that can be provided for a hash algorithm.
|
* Usage recommendation that can be provided for a hash algorithm.
|
||||||
|
* <p>
|
||||||
|
* Use the following rules of thumb:
|
||||||
|
* <ul>
|
||||||
|
* <li>Hashes using MD5 may be {@link #ACCEPTABLE} but never {@link #RECOMMENDED}.</li>
|
||||||
|
* <li>Hashes using no salt or one based on the username should be {@link #DO_NOT_USE}.</li>
|
||||||
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public enum Usage {
|
public enum Usage {
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
package fr.xephi.authme.security.pbkdf2;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
|
||||||
* <p>
|
* <p>
|
||||||
* <hr />
|
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
||||||
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
|||||||
@ -75,7 +75,7 @@ public interface PBKDF2 {
|
|||||||
/**
|
/**
|
||||||
* Allow setting of configured parameters.
|
* Allow setting of configured parameters.
|
||||||
*
|
*
|
||||||
* @param parameters
|
* @param parameters PBKDF2Parameters
|
||||||
*/
|
*/
|
||||||
void setParameters(PBKDF2Parameters parameters);
|
void setParameters(PBKDF2Parameters parameters);
|
||||||
|
|
||||||
|
|||||||
@ -8,20 +8,17 @@ import java.security.SecureRandom;
|
|||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
||||||
* <p>
|
* </p><p>
|
||||||
* Version 2.0
|
* Version 2.0
|
||||||
* <p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* PBKDF2 (P, S, c, dkLen)
|
* PBKDF2 (P, S, c, dkLen)
|
||||||
* <p>
|
* </p>
|
||||||
* <p>
|
|
||||||
* Options:
|
* Options:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
||||||
* of the pseudorandom function output). PRF is pluggable.</li>
|
* of the pseudorandom function output). PRF is pluggable.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
|
||||||
* <p>
|
|
||||||
* Input:
|
* Input:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>P password, an octet string</li>
|
* <li>P password, an octet string</li>
|
||||||
@ -30,15 +27,11 @@ import java.security.SecureRandom;
|
|||||||
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
||||||
* at most (2^32 - 1) * hLen</li>
|
* at most (2^32 - 1) * hLen</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
|
||||||
* <p>
|
|
||||||
* Output:
|
* Output:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>DK derived key, a dkLen-octet string</li>
|
* <li>DK derived key, a dkLen-octet string</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* <hr />
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
* </p>
|
* </p>
|
||||||
@ -115,13 +108,14 @@ public class PBKDF2Engine implements PBKDF2 {
|
|||||||
* ISO-8559-1 encoding. Output result as
|
* ISO-8559-1 encoding. Output result as
|
||||||
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
||||||
* encoding.
|
* encoding.
|
||||||
* <p/>
|
* <p>
|
||||||
* Example: Password "password" (without the quotes) leads to
|
* Example: Password "password" (without the quotes) leads to
|
||||||
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
||||||
*
|
* </p>
|
||||||
* @param args Supply the password as argument.
|
* @param args Supply the password as argument.
|
||||||
*
|
*
|
||||||
* @throws IOException * @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
|
* @throws IOException an ioexception occured
|
||||||
|
* @throws NoSuchAlgorithmException a NoSuchAlgorithmException occured
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
throws IOException, NoSuchAlgorithmException {
|
throws IOException, NoSuchAlgorithmException {
|
||||||
@ -266,8 +260,8 @@ public class PBKDF2Engine implements PBKDF2 {
|
|||||||
/**
|
/**
|
||||||
* Integer division with ceiling function.
|
* Integer division with ceiling function.
|
||||||
*
|
*
|
||||||
* @param a
|
* @param a Integer
|
||||||
* @param b
|
* @param b Integer
|
||||||
*
|
*
|
||||||
* @return ceil(a/b) * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
* @return ceil(a/b) * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||||
* 2.</a>
|
* 2.</a>
|
||||||
@ -288,7 +282,7 @@ public class PBKDF2Engine implements PBKDF2 {
|
|||||||
* @param prf Pseudo Random Function
|
* @param prf Pseudo Random Function
|
||||||
* @param S Salt as array of bytes
|
* @param S Salt as array of bytes
|
||||||
* @param c Iteration count
|
* @param c Iteration count
|
||||||
* @param blockIndex
|
* @param blockIndex Integer
|
||||||
*
|
*
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||||
* 3.</a>
|
* 3.</a>
|
||||||
@ -314,8 +308,8 @@ public class PBKDF2Engine implements PBKDF2 {
|
|||||||
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
||||||
* buffer must be same length or less than source buffer.
|
* buffer must be same length or less than source buffer.
|
||||||
*
|
*
|
||||||
* @param dest
|
* @param dest byte array
|
||||||
* @param src
|
* @param src byte array
|
||||||
*/
|
*/
|
||||||
protected void xor(byte[] dest, byte[] src) {
|
protected void xor(byte[] dest, byte[] src) {
|
||||||
for (int i = 0; i < dest.length; i++) {
|
for (int i = 0; i < dest.length; i++) {
|
||||||
@ -326,9 +320,9 @@ public class PBKDF2Engine implements PBKDF2 {
|
|||||||
/**
|
/**
|
||||||
* Four-octet encoding of the integer i, most significant octet first.
|
* Four-octet encoding of the integer i, most significant octet first.
|
||||||
*
|
*
|
||||||
* @param dest
|
* @param dest byte array
|
||||||
* @param offset
|
* @param offset Integer
|
||||||
* @param i
|
* @param i Integer
|
||||||
*
|
*
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
||||||
* 3.</a>
|
* 3.</a>
|
||||||
|
|||||||
@ -5,8 +5,6 @@ package fr.xephi.authme.security.pbkdf2;
|
|||||||
* Parameter data holder for PBKDF2 configuration.
|
* Parameter data holder for PBKDF2 configuration.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* <hr />
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
* </p>
|
* </p>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Xephi59
|
* @author Xephi59
|
||||||
* @version $Revision: 1.0 $
|
* @version $Revision: 1.0 $
|
||||||
@ -88,7 +88,7 @@ public class OtherAccounts extends CustomConfiguration {
|
|||||||
*
|
*
|
||||||
* @param uuid UUID
|
* @param uuid UUID
|
||||||
*
|
*
|
||||||
* @return List<String>
|
* @return StringList
|
||||||
*/
|
*/
|
||||||
public List<String> getAllPlayersByUUID(UUID uuid) {
|
public List<String> getAllPlayersByUUID(UUID uuid) {
|
||||||
return this.getStringList(uuid.toString());
|
return this.getStringList(uuid.toString());
|
||||||
|
|||||||
@ -1,32 +1,27 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSource.DataSourceType;
|
||||||
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.util.Wrapper;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSource.DataSourceType;
|
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
|
||||||
import fr.xephi.authme.util.Wrapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public final class Settings {
|
public final class Settings {
|
||||||
@ -122,7 +117,7 @@ public final class Settings {
|
|||||||
/**
|
/**
|
||||||
* Method reload.
|
* Method reload.
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception if something went wrong
|
||||||
*/
|
*/
|
||||||
public static void reload() throws Exception {
|
public static void reload() throws Exception {
|
||||||
plugin.getLogger().info("Loading Configuration File...");
|
plugin.getLogger().info("Loading Configuration File...");
|
||||||
@ -141,7 +136,6 @@ public final class Settings {
|
|||||||
messageFile = new File(PLUGIN_FOLDER, "messages" + File.separator + "messages_" + messagesLanguage + ".yml");
|
messageFile = new File(PLUGIN_FOLDER, "messages" + File.separator + "messages_" + messagesLanguage + ".yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void loadVariables() {
|
public static void loadVariables() {
|
||||||
helpHeader = configFile.getString("settings.helpHeader", "AuthMeReloaded");
|
helpHeader = configFile.getString("settings.helpHeader", "AuthMeReloaded");
|
||||||
messagesLanguage = checkLang(configFile.getString("settings.messagesLanguage", "en").toLowerCase());
|
messagesLanguage = checkLang(configFile.getString("settings.messagesLanguage", "en").toLowerCase());
|
||||||
@ -311,35 +305,22 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String loadEmailText() {
|
private static String loadEmailText() {
|
||||||
if (!EMAIL_FILE.exists())
|
if (!EMAIL_FILE.exists()) {
|
||||||
saveDefaultEmailText();
|
plugin.saveResource("email.html", false);
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
try {
|
|
||||||
BufferedReader in = new BufferedReader(new FileReader(EMAIL_FILE));
|
|
||||||
String s;
|
|
||||||
while ((s = in.readLine()) != null)
|
|
||||||
str.append(s);
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
}
|
||||||
return str.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void saveDefaultEmailText() {
|
|
||||||
InputStream file = plugin.getResource("email.html");
|
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
try {
|
try {
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(file, Charset.forName("utf-8")));
|
return Files.toString(EMAIL_FILE, Charsets.UTF_8);
|
||||||
String s;
|
} catch (IOException e) {
|
||||||
while ((s = in.readLine()) != null)
|
ConsoleLogger.showError(e.getMessage());
|
||||||
str.append(s);
|
ConsoleLogger.writeStackTrace(e);
|
||||||
in.close();
|
return "";
|
||||||
Files.touch(EMAIL_FILE);
|
|
||||||
Files.write(str.toString(), EMAIL_FILE, Charsets.UTF_8);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key the key to set
|
||||||
|
* @param value the value to set
|
||||||
|
*/
|
||||||
public static void setValue(String key, Object value) {
|
public static void setValue(String key, Object value) {
|
||||||
instance.set(key, value);
|
instance.set(key, value);
|
||||||
save();
|
save();
|
||||||
@ -380,8 +361,9 @@ public final class Settings {
|
|||||||
* return false if ip and name doesn't match with player that join the
|
* return false if ip and name doesn't match with player that join the
|
||||||
* server, so player has a restricted access
|
* server, so player has a restricted access
|
||||||
*
|
*
|
||||||
* @param name String
|
* @param name String
|
||||||
* @param ip String
|
* @param ip String
|
||||||
|
* @param domain String
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@ -396,14 +378,12 @@ public final class Settings {
|
|||||||
String testIp = args[1];
|
String testIp = args[1];
|
||||||
if (testName.equalsIgnoreCase(name)) {
|
if (testName.equalsIgnoreCase(name)) {
|
||||||
nameFound = true;
|
nameFound = true;
|
||||||
if (ip != null)
|
if (ip != null) {
|
||||||
{
|
|
||||||
if (testIp.equalsIgnoreCase(ip)) {
|
if (testIp.equalsIgnoreCase(ip)) {
|
||||||
trueOnce = true;
|
trueOnce = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (domain != null)
|
if (domain != null) {
|
||||||
{
|
|
||||||
if (testIp.equalsIgnoreCase(domain)) {
|
if (testIp.equalsIgnoreCase(domain)) {
|
||||||
trueOnce = true;
|
trueOnce = true;
|
||||||
}
|
}
|
||||||
@ -737,10 +717,9 @@ public final class Settings {
|
|||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contains("settings.preventOtherCase"))
|
if (!contains("settings.preventOtherCase")) {
|
||||||
{
|
set("settings.preventOtherCase", false);
|
||||||
set("settings.preventOtherCase", false);
|
changes = true;
|
||||||
changes = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contains("Email.mailText")) {
|
if (contains("Email.mailText")) {
|
||||||
@ -749,15 +728,14 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!contains("Security.stop.kickPlayersBeforeStopping")) {
|
if (!contains("Security.stop.kickPlayersBeforeStopping")) {
|
||||||
set("Security.stop.kickPlayersBeforeStopping", true);
|
set("Security.stop.kickPlayersBeforeStopping", true);
|
||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contains("Email.emailOauth2Token"))
|
if (!contains("Email.emailOauth2Token"))
|
||||||
set("Email.emailOauth2Token", "");
|
set("Email.emailOauth2Token", "");
|
||||||
|
|
||||||
if (!contains("Hook.sendPlayerTo"))
|
if (!contains("Hook.sendPlayerTo")) {
|
||||||
{
|
|
||||||
set("Hooks.sendPlayerTo", "");
|
set("Hooks.sendPlayerTo", "");
|
||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
@ -768,11 +746,21 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private static boolean contains(String path) {
|
private static boolean contains(String path) {
|
||||||
return configFile.contains(path);
|
return configFile.contains(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public because it's used in AuthMe at one place
|
// public because it's used in AuthMe at one place
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path String
|
||||||
|
* @param value String
|
||||||
|
*/
|
||||||
public void set(String path, Object value) {
|
public void set(String path, Object value) {
|
||||||
configFile.set(path, value);
|
configFile.set(path, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@ public final class CollectionUtils {
|
|||||||
/**
|
/**
|
||||||
* Get a range from a list based on start and count parameters in a safe way.
|
* Get a range from a list based on start and count parameters in a safe way.
|
||||||
*
|
*
|
||||||
|
* @param <T> element
|
||||||
|
* @param list The List
|
||||||
* @param start The start index
|
* @param start The start index
|
||||||
* @param count The number of elements to add
|
* @param count The number of elements to add
|
||||||
*
|
*
|
||||||
@ -34,6 +36,8 @@ public final class CollectionUtils {
|
|||||||
/**
|
/**
|
||||||
* Get all elements from a list starting from the given index.
|
* Get all elements from a list starting from the given index.
|
||||||
*
|
*
|
||||||
|
* @param <T> element
|
||||||
|
* @param list The List
|
||||||
* @param start The start index
|
* @param start The start index
|
||||||
*
|
*
|
||||||
* @return The sublist of all elements from index {@code start} and on; empty list
|
* @return The sublist of all elements from index {@code start} and on; empty list
|
||||||
@ -46,6 +50,11 @@ public final class CollectionUtils {
|
|||||||
return getRange(list, start, list.size() - start);
|
return getRange(list, start, list.size() - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <T> element
|
||||||
|
* @param coll Collection
|
||||||
|
* @return boolean Boolean
|
||||||
|
*/
|
||||||
public static <T> boolean isEmpty(Collection<T> coll) {
|
public static <T> boolean isEmpty(Collection<T> coll) {
|
||||||
return coll == null || coll.isEmpty();
|
return coll == null || coll.isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,120 +45,144 @@ commands:
|
|||||||
usage: /converter <datatype>
|
usage: /converter <datatype>
|
||||||
permissions:
|
permissions:
|
||||||
authme.admin.*:
|
authme.admin.*:
|
||||||
description: Gives access to all authme admin commands
|
description: Give access to all admin commands.
|
||||||
children:
|
children:
|
||||||
authme.admin.reload: true
|
authme.admin.accounts: true
|
||||||
authme.admin.register: true
|
authme.admin.changemail: true
|
||||||
authme.admin.changepassword: true
|
authme.admin.changepassword: true
|
||||||
authme.admin.unregister: true
|
authme.admin.converter: true
|
||||||
authme.admin.purge: true
|
authme.admin.firstspawn: true
|
||||||
authme.seeOtherAccounts: true # This isn't a child of the admin section! Probably doesn't work.
|
authme.admin.forcelogin: true
|
||||||
authme.admin.lastlogin: true
|
authme.admin.getemail: true
|
||||||
authme.admin.getemail: true
|
authme.admin.getip: true
|
||||||
authme.admin.chgemail: true
|
authme.admin.lastlogin: true
|
||||||
authme.admin.purgelastpos: true
|
authme.admin.purge: true
|
||||||
authme.admin.switchantibot: true
|
authme.admin.purgebannedplayers: true
|
||||||
authme.bypassantibot: true # This isn't a child of the admin section! Probably doesn't work.
|
authme.admin.purgelastpos: true
|
||||||
authme.admin.getip: true
|
authme.admin.register: true
|
||||||
authme.admin.converter: true
|
authme.admin.reload: true
|
||||||
authme.admin.resetposition: true
|
authme.admin.setfirstspawn: true
|
||||||
authme.admin.forcelogin: true
|
authme.admin.setspawn: true
|
||||||
authme.register:
|
authme.admin.spawn: true
|
||||||
description: Register an account
|
authme.admin.switchantibot: true
|
||||||
default: true
|
authme.admin.unregister: true
|
||||||
authme.login:
|
|
||||||
description: Login into a account
|
|
||||||
default: true
|
|
||||||
authme.changepassword:
|
|
||||||
description: Change password of a account
|
|
||||||
default: true
|
|
||||||
authme.logout:
|
|
||||||
description: Logout
|
|
||||||
default: true
|
|
||||||
authme.email:
|
|
||||||
description: Email
|
|
||||||
default: true
|
|
||||||
authme.allow2accounts:
|
|
||||||
description: allow more accounts for same ip
|
|
||||||
default: false
|
|
||||||
authme.seeOtherAccounts:
|
|
||||||
description: display other accounts about a player when he logs in
|
|
||||||
default: false
|
|
||||||
authme.unregister:
|
|
||||||
description: unregister your account
|
|
||||||
default: true
|
|
||||||
authme.admin.reload:
|
|
||||||
description: AuthMe reload commands
|
|
||||||
default: op
|
|
||||||
authme.admin.register:
|
authme.admin.register:
|
||||||
description: AuthMe register command
|
description: Administrator command to register a new user.
|
||||||
default: op
|
|
||||||
authme.admin.changepassword:
|
|
||||||
description: AuthMe changepassword command
|
|
||||||
default: op
|
default: op
|
||||||
authme.admin.unregister:
|
authme.admin.unregister:
|
||||||
description: AuthMe unregister command
|
description: Administrator command to unregister an existing user.
|
||||||
default: op
|
|
||||||
authme.admin.purge:
|
|
||||||
description: AuthMe unregister command
|
|
||||||
default: op
|
|
||||||
authme.admin.lastlogin:
|
|
||||||
description: Get last login date about a player
|
|
||||||
default: op
|
|
||||||
authme.admin.getemail:
|
|
||||||
description: Get last email about a player
|
|
||||||
default: op
|
|
||||||
authme.admin.chgemail:
|
|
||||||
description: Change a player email
|
|
||||||
default: op
|
|
||||||
authme.admin.accounts:
|
|
||||||
description: Display Players Accounts
|
|
||||||
default: op
|
|
||||||
authme.captcha:
|
|
||||||
description: Captcha
|
|
||||||
default: true
|
|
||||||
authme.admin.setspawn:
|
|
||||||
description: Set the AuthMe spawn point
|
|
||||||
default: op
|
|
||||||
authme.admin.spawn:
|
|
||||||
description: Teleport to AuthMe spawn point
|
|
||||||
default: op
|
|
||||||
authme.vip:
|
|
||||||
description: Allow vip slot when the server is full
|
|
||||||
default: op
|
|
||||||
authme.admin.purgebannedplayers:
|
|
||||||
description: Purge banned players
|
|
||||||
default: op
|
|
||||||
authme.bypassforcesurvival:
|
|
||||||
description: Bypass all ForceSurvival features
|
|
||||||
default: false
|
|
||||||
authme.admin.purgelastpos:
|
|
||||||
description: Purge last pos of players
|
|
||||||
default: op
|
|
||||||
authme.admin.switchantibot:
|
|
||||||
description: Switch AntiBot mode on/off
|
|
||||||
default: op
|
|
||||||
authme.bypassantibot:
|
|
||||||
description: Bypass the AntiBot check
|
|
||||||
default: op
|
|
||||||
authme.admin.setfirstspawn:
|
|
||||||
description: Set the AuthMe First Spawn Point
|
|
||||||
default: op
|
|
||||||
authme.admin.firstspawn:
|
|
||||||
description: Teleport to AuthMe First Spawn Point
|
|
||||||
default: op
|
|
||||||
authme.admin.getip:
|
|
||||||
description: Get IP from a player ( fake and real )
|
|
||||||
default: op
|
|
||||||
authme.admin.converter:
|
|
||||||
description: Allow /converter command
|
|
||||||
default: op
|
|
||||||
authme.admin.resetposition:
|
|
||||||
description: Reset last position for a player
|
|
||||||
default: op
|
default: op
|
||||||
authme.admin.forcelogin:
|
authme.admin.forcelogin:
|
||||||
description: Force login for that player
|
description: Administrator command to force-login an existing user.
|
||||||
default: op
|
default: op
|
||||||
authme.canbeforced:
|
authme.admin.changepassword:
|
||||||
description: Can this player be forced to login
|
description: Administrator command to change the password of a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.lastlogin:
|
||||||
|
description: Administrator command to see the last login date and time of a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.accounts:
|
||||||
|
description: Administrator command to see all accounts associated with a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.getemail:
|
||||||
|
description: Administrator command to get the email address of a user, if set.
|
||||||
|
default: op
|
||||||
|
authme.admin.changemail:
|
||||||
|
description: Administrator command to set or change the email address of a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.getip:
|
||||||
|
description: Administrator command to get the last known IP of a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.spawn:
|
||||||
|
description: Administrator command to teleport to the AuthMe spawn.
|
||||||
|
default: op
|
||||||
|
authme.admin.setspawn:
|
||||||
|
description: Administrator command to set the AuthMe spawn.
|
||||||
|
default: op
|
||||||
|
authme.admin.firstspawn:
|
||||||
|
description: Administrator command to teleport to the first AuthMe spawn.
|
||||||
|
default: op
|
||||||
|
authme.admin.setfirstspawn:
|
||||||
|
description: Administrator command to set the first AuthMe spawn.
|
||||||
|
default: op
|
||||||
|
authme.admin.purge:
|
||||||
|
description: Administrator command to purge old user data.
|
||||||
|
default: op
|
||||||
|
authme.admin.purgelastpos:
|
||||||
|
description: Administrator command to purge the last position of a user.
|
||||||
|
default: op
|
||||||
|
authme.admin.purgebannedplayers:
|
||||||
|
description: Administrator command to purge all data associated with banned players.
|
||||||
|
default: op
|
||||||
|
authme.admin.switchantibot:
|
||||||
|
description: Administrator command to toggle the AntiBot protection status.
|
||||||
|
default: op
|
||||||
|
authme.admin.converter:
|
||||||
|
description: Administrator command to convert old or other data to AuthMe data.
|
||||||
|
default: op
|
||||||
|
authme.admin.reload:
|
||||||
|
description: Administrator command to reload the plugin configuration.
|
||||||
|
default: op
|
||||||
|
authme.player.*:
|
||||||
|
description: Permission to use all player (non-admin) commands.
|
||||||
|
children:
|
||||||
|
authme.player.allow2accounts: true
|
||||||
|
authme.player.bypassantibot: true
|
||||||
|
authme.player.bypassforcesurvival: true
|
||||||
|
authme.player.canbeforced: true
|
||||||
|
authme.player.captcha: true
|
||||||
|
authme.player.changepassword: true
|
||||||
|
authme.player.email.add: true
|
||||||
|
authme.player.email.change: true
|
||||||
|
authme.player.email.recover: true
|
||||||
|
authme.player.login: true
|
||||||
|
authme.player.logout: true
|
||||||
|
authme.player.register: true
|
||||||
|
authme.player.seeotheraccounts: true
|
||||||
|
authme.player.unregister: true
|
||||||
|
authme.player.vip: true
|
||||||
|
authme.player.bypassantibot:
|
||||||
|
description: Permission node to bypass AntiBot protection.
|
||||||
|
default: false
|
||||||
|
authme.player.vip:
|
||||||
|
description: Permission node to identify VIP users.
|
||||||
|
default: false
|
||||||
|
authme.player.login:
|
||||||
|
description: Command permission to login.
|
||||||
default: true
|
default: true
|
||||||
|
authme.player.logout:
|
||||||
|
description: Command permission to logout.
|
||||||
|
default: true
|
||||||
|
authme.player.register:
|
||||||
|
description: Command permission to register.
|
||||||
|
default: true
|
||||||
|
authme.player.unregister:
|
||||||
|
description: Command permission to unregister.
|
||||||
|
default: true
|
||||||
|
authme.player.changepassword:
|
||||||
|
description: Command permission to change the password.
|
||||||
|
default: true
|
||||||
|
authme.player.email.add:
|
||||||
|
description: Command permission to add an email address.
|
||||||
|
default: false
|
||||||
|
authme.player.email.change:
|
||||||
|
description: Command permission to change the email address.
|
||||||
|
default: false
|
||||||
|
authme.player.email.recover:
|
||||||
|
description: Command permission to recover an account using it's email address.
|
||||||
|
default: false
|
||||||
|
authme.player.captcha:
|
||||||
|
description: Command permission to use captcha.
|
||||||
|
default: false
|
||||||
|
authme.player.canbeforced:
|
||||||
|
description: Permission for users a login can be forced to.
|
||||||
|
default: false
|
||||||
|
authme.player.bypassforcesurvival:
|
||||||
|
description: Permission for users to bypass force-survival mode.
|
||||||
|
default: false
|
||||||
|
authme.player.allow2accounts:
|
||||||
|
description: Permission for users to allow two accounts.
|
||||||
|
default: false
|
||||||
|
authme.player.seeotheraccounts:
|
||||||
|
description: Permission for user to see other accounts.
|
||||||
|
default: false
|
||||||
|
|||||||
@ -142,30 +142,44 @@ public abstract class AbstractEncryptionMethodTest {
|
|||||||
return method.comparePassword(password, hashes.get(password), USERNAME);
|
return method.comparePassword(password, hashes.get(password), USERNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(); }
|
/**
|
||||||
// TODO #364: Remove this method
|
* Generates a test class for a given encryption method. Simply create a test class and run the following code,
|
||||||
|
* replacing {@code XXX} with the actual class:
|
||||||
|
* <p>
|
||||||
|
* <code>@org.junit.Test public void generate() { AbstractEncryptionMethodTest.generateTest(new XXX()); }</code>
|
||||||
|
* <p>
|
||||||
|
* The output is the entire test class.
|
||||||
|
*
|
||||||
|
* @param method The method to create a test class for
|
||||||
|
*/
|
||||||
static void generateTest(EncryptionMethod method) {
|
static void generateTest(EncryptionMethod method) {
|
||||||
String className = method.getClass().getSimpleName();
|
String className = method.getClass().getSimpleName();
|
||||||
|
// Create javadoc and "public class extends" and the constructor call "super(new Class(),"
|
||||||
System.out.println("/**\n * Test for {@link " + className + "}.\n */");
|
System.out.println("/**\n * Test for {@link " + className + "}.\n */");
|
||||||
System.out.println("public class " + className + "Test extends AbstractEncryptionMethodTest {");
|
System.out.println("public class " + className + "Test extends AbstractEncryptionMethodTest {");
|
||||||
System.out.println("\n\tpublic " + className + "Test() {");
|
System.out.println("\n\tpublic " + className + "Test() {");
|
||||||
System.out.println("\t\tsuper(new " + className + "(),");
|
System.out.println("\t\tsuper(new " + className + "(),");
|
||||||
|
|
||||||
|
// Iterate through the GIVEN_PASSWORDS and generate a hash so we can always check it later
|
||||||
String delim = ", ";
|
String delim = ", ";
|
||||||
for (String password : GIVEN_PASSWORDS) {
|
for (String password : GIVEN_PASSWORDS) {
|
||||||
if (password.equals(GIVEN_PASSWORDS[GIVEN_PASSWORDS.length - 1])) {
|
if (password.equals(GIVEN_PASSWORDS[GIVEN_PASSWORDS.length - 1])) {
|
||||||
delim = "); ";
|
delim = "); ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encr. method uses separate salt, so we need to call the constructor that takes HashedPassword instances
|
||||||
if (method.hasSeparateSalt()) {
|
if (method.hasSeparateSalt()) {
|
||||||
HashedPassword hashedPassword = method.computeHash(password, USERNAME);
|
HashedPassword hashedPassword = method.computeHash(password, USERNAME);
|
||||||
System.out.println(String.format("\t\tnew HashedPassword(\"%s\", \"%s\")%s// %s",
|
System.out.println(String.format("\t\tnew HashedPassword(\"%s\", \"%s\")%s// %s",
|
||||||
hashedPassword.getHash(), hashedPassword.getSalt(), delim, password));
|
hashedPassword.getHash(), hashedPassword.getSalt(), delim, password));
|
||||||
} else {
|
} else {
|
||||||
|
// Encryption method doesn't have separate salt, so simply pass the generated hash to the constructor
|
||||||
System.out.println("\t\t\"" + method.computeHash(password, USERNAME).getHash()
|
System.out.println("\t\t\"" + method.computeHash(password, USERNAME).getHash()
|
||||||
+ "\"" + delim + "// " + password);
|
+ "\"" + delim + "// " + password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the constructor and class declarations
|
||||||
System.out.println("\t}");
|
System.out.println("\t}");
|
||||||
System.out.println("\n}");
|
System.out.println("\n}");
|
||||||
}
|
}
|
||||||
|
|||||||
78
src/tools/docs/hash_algorithms.md
Normal file
78
src/tools/docs/hash_algorithms.md
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
|
<!-- File auto-generated on Thu Dec 31 13:41:44 CET 2015. See hashmethods/hash_algorithms.tpl.md -->
|
||||||
|
|
||||||
|
## Hash Algorithms
|
||||||
|
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||||
|
|
||||||
|
|
||||||
|
Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate?
|
||||||
|
--------- | -------------- | ----------- | ----- | --- | --------- | ------ | ---------
|
||||||
|
BCRYPT | Recommended | 60 | | | Text | |
|
||||||
|
BCRYPT2Y | Recommended | 60 | | | Text | 22 |
|
||||||
|
CRAZYCRYPT1 | Do not use | 128 | | | Username | |
|
||||||
|
DOUBLEMD5 | Do not use | 32 | | | None | |
|
||||||
|
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
||||||
|
JOOMLA | Recommended | 65 | | | Text | 32 |
|
||||||
|
MD5 | Do not use | 32 | | | None | |
|
||||||
|
MD5VB | Acceptable | 56 | | | Text | 16 |
|
||||||
|
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
||||||
|
PBKDF2 | Does not work | 330 | | | Text | 12 |
|
||||||
|
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
|
||||||
|
PHPBB | Acceptable | 34 | | | Text | 16 |
|
||||||
|
PHPFUSION | Do not use | 64 | Y | | | | Y
|
||||||
|
ROYALAUTH | Do not use | 128 | | | None | |
|
||||||
|
SALTED2MD5 | Acceptable | 32 | | | Text | | Y
|
||||||
|
SALTEDSHA512 | Recommended | 128 | | | | | Y
|
||||||
|
SHA1 | Do not use | 40 | | | None | |
|
||||||
|
SHA256 | Recommended | 86 | | | Text | 16 |
|
||||||
|
SHA512 | Do not use | 128 | | | None | |
|
||||||
|
SMF | Do not use | 40 | | | Username | |
|
||||||
|
WBB3 | Acceptable | 40 | | | Text | 40 | Y
|
||||||
|
WBB4 | Does not work | 60 | | | Text | 8 |
|
||||||
|
WHIRLPOOL | Do not use | 128 | | | None | |
|
||||||
|
WORDPRESS | Do not use | 34 | | | Text | 9 |
|
||||||
|
XAUTH | Recommended | 140 | | | Text | 12 |
|
||||||
|
CUSTOM | | | | | | | |
|
||||||
|
|
||||||
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
|
|
||||||
|
### Columns
|
||||||
|
#### Algorithm
|
||||||
|
The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
|
||||||
|
You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
|
||||||
|
|
||||||
|
#### Recommendation
|
||||||
|
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
|
||||||
|
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
|
||||||
|
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
|
||||||
|
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
|
||||||
|
- Does not work: The algorithm does not work properly; do not use.
|
||||||
|
|
||||||
|
#### Hash Length
|
||||||
|
The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
|
||||||
|
whether an algorithm is secure or not.
|
||||||
|
|
||||||
|
#### ASCII
|
||||||
|
If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
|
||||||
|
"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
|
||||||
|
|
||||||
|
#### Salt Columns
|
||||||
|
Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
|
||||||
|
the salt the algorithm uses.
|
||||||
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
|
|
||||||
|
##### Salt Type
|
||||||
|
We do not recommend the usage
|
||||||
|
of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
|
||||||
|
salt the algorithm uses:
|
||||||
|
- Text: randomly generated text (see also the following column, "Length")
|
||||||
|
- Username: the salt is constructed from the username (bad)
|
||||||
|
- None: the algorithm uses no salt (bad)
|
||||||
|
|
||||||
|
##### Length
|
||||||
|
If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
|
||||||
|
If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
|
||||||
|
|
||||||
|
##### Separate
|
||||||
|
If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
|
||||||
|
or bad.
|
||||||
135
src/tools/hashmethods/EncryptionMethodInfoGatherer.java
Normal file
135
src/tools/hashmethods/EncryptionMethodInfoGatherer.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package hashmethods;
|
||||||
|
|
||||||
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
|
import fr.xephi.authme.security.crypts.HexSaltedMethod;
|
||||||
|
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
|
||||||
|
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Sets.newHashSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gathers information on {@link fr.xephi.authme.security.crypts.EncryptionMethod} implementations based on
|
||||||
|
* the annotations in {@link fr.xephi.authme.security.crypts.description}.
|
||||||
|
*/
|
||||||
|
public class EncryptionMethodInfoGatherer {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private final static Set<Class<? extends Annotation>> RELEVANT_ANNOTATIONS =
|
||||||
|
newHashSet(HasSalt.class, Recommendation.class, AsciiRestricted.class);
|
||||||
|
|
||||||
|
private Map<HashAlgorithm, MethodDescription> descriptions;
|
||||||
|
|
||||||
|
public EncryptionMethodInfoGatherer() {
|
||||||
|
descriptions = new LinkedHashMap<>();
|
||||||
|
constructDescriptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<HashAlgorithm, MethodDescription> getDescriptions() {
|
||||||
|
return descriptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void constructDescriptions() {
|
||||||
|
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||||
|
Class<? extends EncryptionMethod> methodClazz = algorithm.getClazz();
|
||||||
|
if (!HashAlgorithm.CUSTOM.equals(algorithm) && !methodClazz.isAnnotationPresent(Deprecated.class)) {
|
||||||
|
MethodDescription description = createDescription(methodClazz);
|
||||||
|
descriptions.put(algorithm, description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MethodDescription createDescription(Class<? extends EncryptionMethod> clazz) {
|
||||||
|
EncryptionMethod method = instantiateMethod(clazz);
|
||||||
|
MethodDescription description = new MethodDescription(clazz);
|
||||||
|
description.setHashLength(method.computeHash("test", "user").getHash().length());
|
||||||
|
description.setHasSeparateSalt(method.hasSeparateSalt());
|
||||||
|
|
||||||
|
Map<Class<?>, Annotation> annotationMap = gatherAnnotations(clazz);
|
||||||
|
if (annotationMap.containsKey(HasSalt.class)) {
|
||||||
|
setSaltInformation(description, returnTyped(annotationMap, HasSalt.class), method);
|
||||||
|
}
|
||||||
|
if (annotationMap.containsKey(Recommendation.class)) {
|
||||||
|
description.setUsage(returnTyped(annotationMap, Recommendation.class).value());
|
||||||
|
}
|
||||||
|
if (annotationMap.containsKey(AsciiRestricted.class)) {
|
||||||
|
description.setAsciiRestricted(true);
|
||||||
|
}
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Class<?>, Annotation> gatherAnnotations(Class<?> methodClass) {
|
||||||
|
// Note ljacqu 20151231: The map could be Map<Class<? extends Annotation>, Annotation> and it has the constraint
|
||||||
|
// that for a key Class<T>, the value is of type T. We write a simple "Class<?>" for brevity.
|
||||||
|
Map<Class<?>, Annotation> collection = new HashMap<>();
|
||||||
|
Class<?> currentMethodClass = methodClass;
|
||||||
|
while (currentMethodClass != null) {
|
||||||
|
getRelevantAnnotations(currentMethodClass, collection);
|
||||||
|
currentMethodClass = getSuperClass(currentMethodClass);
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters could be Class<? extends EncryptionMethod>; Map<Class<? extends Annotation>, Annotation>
|
||||||
|
// but the constraint doesn't have any technical relevance, so just clutters the code
|
||||||
|
private static void getRelevantAnnotations(Class<?> methodClass, Map<Class<?>, Annotation> collection) {
|
||||||
|
for (Annotation annotation : methodClass.getAnnotations()) {
|
||||||
|
if (RELEVANT_ANNOTATIONS.contains(annotation.annotationType())
|
||||||
|
&& !collection.containsKey(annotation.annotationType())) {
|
||||||
|
collection.put(annotation.annotationType(), annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the super class of the given encryption method if it is also of EncryptionMethod type.
|
||||||
|
* (Anything beyond EncryptionMethod is not of interest.)
|
||||||
|
*/
|
||||||
|
private static Class<?> getSuperClass(Class<?> methodClass) {
|
||||||
|
Class<?> zuper = methodClass.getSuperclass();
|
||||||
|
if (EncryptionMethod.class.isAssignableFrom(zuper)) {
|
||||||
|
return zuper;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the salt information for the given encryption method and the found {@link HasSalt} annotation.
|
||||||
|
* Also gets the salt length from {@link HexSaltedMethod#getSaltLength()} for such instances.
|
||||||
|
*
|
||||||
|
* @param description The description to update
|
||||||
|
* @param hasSalt The associated HasSalt annotation
|
||||||
|
* @param method The encryption method
|
||||||
|
*/
|
||||||
|
private static void setSaltInformation(MethodDescription description, HasSalt hasSalt, EncryptionMethod method) {
|
||||||
|
description.setSaltType(hasSalt.value());
|
||||||
|
if (hasSalt.length() != 0) {
|
||||||
|
description.setSaltLength(hasSalt.length());
|
||||||
|
} else if (method instanceof HexSaltedMethod) {
|
||||||
|
int saltLength = ((HexSaltedMethod) method).getSaltLength();
|
||||||
|
description.setSaltLength(saltLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EncryptionMethod instantiateMethod(Class<? extends EncryptionMethod> clazz) {
|
||||||
|
try {
|
||||||
|
return clazz.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("Could not instantiate " + clazz, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience method for retrieving an annotation in a typed fashion.
|
||||||
|
// We know implicitly that the key of the map always corresponds to the type of the value
|
||||||
|
private static <T> T returnTyped(Map<Class<?>, Annotation> map, Class<T> key) {
|
||||||
|
return key.cast(map.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
100
src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
Normal file
100
src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package hashmethods;
|
||||||
|
|
||||||
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.util.WrapperMock;
|
||||||
|
import utils.ANewMap;
|
||||||
|
import utils.FileUtils;
|
||||||
|
import utils.TagReplacer;
|
||||||
|
import utils.ToolTask;
|
||||||
|
import utils.ToolsConstants;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task for generating the markdown page describing the AuthMe hash algorithms.
|
||||||
|
*
|
||||||
|
* @see {@link fr.xephi.authme.security.HashAlgorithm}
|
||||||
|
*/
|
||||||
|
public class HashAlgorithmsDescriptionTask implements ToolTask {
|
||||||
|
|
||||||
|
private static final String CUR_FOLDER = ToolsConstants.TOOLS_SOURCE_ROOT + "hashmethods/";
|
||||||
|
private static final String OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "hash_algorithms.md";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Scanner scanner) {
|
||||||
|
// Unfortunately, we need the Wrapper to be around to work with Settings, and certain encryption methods
|
||||||
|
// directly read from the Settings file
|
||||||
|
WrapperMock.createInstance();
|
||||||
|
Settings.bCryptLog2Rounds = 8;
|
||||||
|
Settings.saltLength = 8;
|
||||||
|
|
||||||
|
// Gather info and construct a row for each method
|
||||||
|
EncryptionMethodInfoGatherer infoGatherer = new EncryptionMethodInfoGatherer();
|
||||||
|
Map<HashAlgorithm, MethodDescription> descriptions = infoGatherer.getDescriptions();
|
||||||
|
final String methodRows = constructMethodRows(descriptions);
|
||||||
|
|
||||||
|
// Write to the docs file
|
||||||
|
Map<String, String> tags = ANewMap.with("method_rows", methodRows).build();
|
||||||
|
FileUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String constructMethodRows(Map<HashAlgorithm, MethodDescription> descriptions) {
|
||||||
|
final String rowTemplate = FileUtils.readFromFile(CUR_FOLDER + "hash_algorithms_row.tpl.md");
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (Map.Entry<HashAlgorithm, MethodDescription> entry : descriptions.entrySet()) {
|
||||||
|
MethodDescription description = entry.getValue();
|
||||||
|
Map<String, String> tags = ANewMap
|
||||||
|
.with("name", asString(entry.getKey()))
|
||||||
|
.and("recommendation", asString(description.getUsage()))
|
||||||
|
.and("hash_length", asString(description.getHashLength()))
|
||||||
|
.and("ascii_restricted", asString(description.isAsciiRestricted()))
|
||||||
|
.and("salt_type", asString(description.getSaltType()))
|
||||||
|
.and("salt_length", asString(description.getSaltLength()))
|
||||||
|
.and("separate_salt", asString(description.hasSeparateSalt()))
|
||||||
|
.build();
|
||||||
|
result.append(TagReplacer.applyReplacements(rowTemplate, tags));
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTaskName() {
|
||||||
|
return "describeHashAlgos";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// String representations
|
||||||
|
// ----
|
||||||
|
private static String asString(boolean value) {
|
||||||
|
return value ? "Y" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String asString(int value) {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String asString(Integer value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String asString(HashAlgorithm value) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <E extends Enum<E>> String asString(E value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Get the enum name and replace something like "DO_NOT_USE" to "Do not use"
|
||||||
|
String enumName = value.toString().replace("_", " ");
|
||||||
|
return enumName.length() > 2
|
||||||
|
? enumName.substring(0, 1) + enumName.substring(1).toLowerCase()
|
||||||
|
: enumName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
85
src/tools/hashmethods/MethodDescription.java
Normal file
85
src/tools/hashmethods/MethodDescription.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package hashmethods;
|
||||||
|
|
||||||
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
|
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of a {@link EncryptionMethod}.
|
||||||
|
*/
|
||||||
|
public class MethodDescription {
|
||||||
|
|
||||||
|
/** The implementation class the description belongs to. */
|
||||||
|
private final Class<? extends EncryptionMethod> method;
|
||||||
|
/** The type of the salt that is used. */
|
||||||
|
private SaltType saltType;
|
||||||
|
/** The length of the salt for SaltType.TEXT salts. */
|
||||||
|
private Integer saltLength;
|
||||||
|
/** The usage recommendation. */
|
||||||
|
private Usage usage;
|
||||||
|
/** Whether or not the encryption method is restricted to ASCII characters for proper functioning. */
|
||||||
|
private boolean asciiRestricted;
|
||||||
|
/** Whether or not the encryption method requires its salt stored separately. */
|
||||||
|
private boolean hasSeparateSalt;
|
||||||
|
/** The length of the hash output, based on a test hash (i.e. assumes same length for all hashes.) */
|
||||||
|
private int hashLength;
|
||||||
|
|
||||||
|
public MethodDescription(Class<? extends EncryptionMethod> method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Trivial getters and setters
|
||||||
|
public Class<? extends EncryptionMethod> getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaltType getSaltType() {
|
||||||
|
return saltType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaltType(SaltType saltType) {
|
||||||
|
this.saltType = saltType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSaltLength() {
|
||||||
|
return saltLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaltLength(int saltLength) {
|
||||||
|
this.saltLength = saltLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Usage getUsage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsage(Usage usage) {
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAsciiRestricted() {
|
||||||
|
return asciiRestricted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsciiRestricted(boolean asciiRestricted) {
|
||||||
|
this.asciiRestricted = asciiRestricted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSeparateSalt() {
|
||||||
|
return hasSeparateSalt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasSeparateSalt(boolean hasSeparateSalt) {
|
||||||
|
this.hasSeparateSalt = hasSeparateSalt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHashLength() {
|
||||||
|
return hashLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashLength(int hashLength) {
|
||||||
|
this.hashLength = hashLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
53
src/tools/hashmethods/hash_algorithms.tpl.md
Normal file
53
src/tools/hashmethods/hash_algorithms.tpl.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!-- {gen_warning} -->
|
||||||
|
<!-- File auto-generated on {gen_date}. See hashmethods/hash_algorithms.tpl.md -->
|
||||||
|
|
||||||
|
## Hash Algorithms
|
||||||
|
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||||
|
|
||||||
|
|
||||||
|
Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate?
|
||||||
|
--------- | -------------- | ----------- | ----- | --- | --------- | ------ | ---------
|
||||||
|
{method_rows}CUSTOM | | | | | | | |
|
||||||
|
|
||||||
|
<!-- {gen_warning} -->
|
||||||
|
|
||||||
|
### Columns
|
||||||
|
#### Algorithm
|
||||||
|
The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
|
||||||
|
You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
|
||||||
|
|
||||||
|
#### Recommendation
|
||||||
|
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
|
||||||
|
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
|
||||||
|
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
|
||||||
|
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
|
||||||
|
- Does not work: The algorithm does not work properly; do not use.
|
||||||
|
|
||||||
|
#### Hash Length
|
||||||
|
The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
|
||||||
|
whether an algorithm is secure or not.
|
||||||
|
|
||||||
|
#### ASCII
|
||||||
|
If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
|
||||||
|
"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
|
||||||
|
|
||||||
|
#### Salt Columns
|
||||||
|
Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
|
||||||
|
the salt the algorithm uses.
|
||||||
|
<!-- {gen_warning} -->
|
||||||
|
|
||||||
|
##### Salt Type
|
||||||
|
We do not recommend the usage
|
||||||
|
of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
|
||||||
|
salt the algorithm uses:
|
||||||
|
- Text: randomly generated text (see also the following column, "Length")
|
||||||
|
- Username: the salt is constructed from the username (bad)
|
||||||
|
- None: the algorithm uses no salt (bad)
|
||||||
|
|
||||||
|
##### Length
|
||||||
|
If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
|
||||||
|
If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
|
||||||
|
|
||||||
|
##### Separate
|
||||||
|
If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
|
||||||
|
or bad.
|
||||||
1
src/tools/hashmethods/hash_algorithms_row.tpl.md
Normal file
1
src/tools/hashmethods/hash_algorithms_row.tpl.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
{name} | {recommendation} | {hash_length} | {ascii_restricted} | | {salt_type} | {salt_length} | {separate_salt}
|
||||||
Loading…
x
Reference in New Issue
Block a user