mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-22 16:48:21 +01:00
Update 2.9.3
* Fix BungeeCord again * Remove useless part of api * Fix register api method * Always store cache with lowercase players name * Remove some useless asynchronous part * Fix some thread problems * Add PBKDF2 method * Fix SQLite problem (world duplicate column) * Fix cannot measure distance between two different world
This commit is contained in:
parent
2522357982
commit
7e7afcbfd6
2
pom.xml
2
pom.xml
@ -24,7 +24,7 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<version>2.9.2</version>
|
<version>2.9.3</version>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bukkit</groupId>
|
<groupId>org.bukkit</groupId>
|
||||||
|
@ -134,7 +134,7 @@ public class Management {
|
|||||||
.getLimboPlayer(name);
|
.getLimboPlayer(name);
|
||||||
final PlayerAuth getAuth = database.getAuth(name);
|
final PlayerAuth getAuth = database.getAuth(name);
|
||||||
if (limbo != null) {
|
if (limbo != null) {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -161,7 +161,7 @@ public class Management {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -189,7 +189,7 @@ public class Management {
|
|||||||
.contains(player.getWorld()
|
.contains(player.getWorld()
|
||||||
.getName())) {
|
.getName())) {
|
||||||
final Location spawnL = spawnLoc;
|
final Location spawnL = spawnLoc;
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -222,7 +222,7 @@ public class Management {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -244,7 +244,7 @@ public class Management {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -256,7 +256,7 @@ public class Management {
|
|||||||
|
|
||||||
if (Settings.protectInventoryBeforeLogInEnabled
|
if (Settings.protectInventoryBeforeLogInEnabled
|
||||||
&& player.hasPlayedBefore()) {
|
&& player.hasPlayedBefore()) {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -312,7 +312,7 @@ public class Management {
|
|||||||
pllog.save();
|
pllog.save();
|
||||||
} catch (NullPointerException ex) {
|
} catch (NullPointerException ex) {
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -343,7 +343,7 @@ public class Management {
|
|||||||
"[AuthMe] " + player.getName()
|
"[AuthMe] " + player.getName()
|
||||||
+ " logged in!"));
|
+ " logged in!"));
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -359,7 +359,7 @@ public class Management {
|
|||||||
try {
|
try {
|
||||||
final int gm = AuthMePlayerListener.gameMode
|
final int gm = AuthMePlayerListener.gameMode
|
||||||
.get(name);
|
.get(name);
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -369,7 +369,7 @@ public class Management {
|
|||||||
});
|
});
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -393,7 +393,7 @@ public class Management {
|
|||||||
.getLimboPlayer(name);
|
.getLimboPlayer(name);
|
||||||
if (limbo != null) {
|
if (limbo != null) {
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -428,7 +428,7 @@ public class Management {
|
|||||||
database.getAuth(name)
|
database.getAuth(name)
|
||||||
.getQuitLocZ() + 0.5D);
|
.getQuitLocZ() + 0.5D);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -448,7 +448,7 @@ public class Management {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -473,7 +473,7 @@ public class Management {
|
|||||||
&& Settings.getForcedWorlds.contains(player
|
&& Settings.getForcedWorlds.contains(player
|
||||||
.getWorld().getName())) {
|
.getWorld().getName())) {
|
||||||
final Location spawnL = spawnLoc;
|
final Location spawnL = spawnLoc;
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -510,7 +510,7 @@ public class Management {
|
|||||||
database.getAuth(name).getQuitLocX() + 0.5D,
|
database.getAuth(name).getQuitLocX() + 0.5D,
|
||||||
database.getAuth(name).getQuitLocY() + 0.5D,
|
database.getAuth(name).getQuitLocY() + 0.5D,
|
||||||
database.getAuth(name).getQuitLocZ() + 0.5D);
|
database.getAuth(name).getQuitLocZ() + 0.5D);
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -528,7 +528,7 @@ public class Management {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -547,7 +547,7 @@ public class Management {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -559,7 +559,7 @@ public class Management {
|
|||||||
|
|
||||||
if (Settings.protectInventoryBeforeLogInEnabled
|
if (Settings.protectInventoryBeforeLogInEnabled
|
||||||
&& player.hasPlayedBefore()) {
|
&& player.hasPlayedBefore()) {
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -612,7 +612,7 @@ public class Management {
|
|||||||
pllog.save();
|
pllog.save();
|
||||||
} catch (NullPointerException ex) {
|
} catch (NullPointerException ex) {
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Bukkit.getServer()
|
Bukkit.getServer()
|
||||||
@ -638,7 +638,7 @@ public class Management {
|
|||||||
"[AuthMe] " + player.getName()
|
"[AuthMe] " + player.getName()
|
||||||
+ " logged in!"));
|
+ " logged in!"));
|
||||||
}
|
}
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
player.saveData();
|
player.saveData();
|
||||||
|
@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import uk.org.whoami.authme.AuthMe;
|
import uk.org.whoami.authme.AuthMe;
|
||||||
import uk.org.whoami.authme.ConsoleLogger;
|
|
||||||
import uk.org.whoami.authme.Utils;
|
import uk.org.whoami.authme.Utils;
|
||||||
import uk.org.whoami.authme.cache.auth.PlayerAuth;
|
import uk.org.whoami.authme.cache.auth.PlayerAuth;
|
||||||
import uk.org.whoami.authme.cache.auth.PlayerCache;
|
import uk.org.whoami.authme.cache.auth.PlayerCache;
|
||||||
@ -73,65 +72,9 @@ public class API {
|
|||||||
return Utils.getInstance().isUnrestricted(player);
|
return Utils.getInstance().isUnrestricted(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isChatAllowed() {
|
|
||||||
return Settings.isChatAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAllowRestrictedIp() {
|
|
||||||
return Settings.isAllowRestrictedIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isBackupActivated() {
|
|
||||||
return Settings.isBackupActivated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isForceSpawnLocOnJoinEnabled() {
|
|
||||||
return Settings.isForceSpawnLocOnJoinEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DataSourceType getDataSource() {
|
|
||||||
return Settings.getDataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMovementRadius() {
|
|
||||||
return Settings.getMovementRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> getJoinPermissions() {
|
|
||||||
return Settings.getJoinPermissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Boolean isPasspartuEnable() {
|
|
||||||
return Settings.enablePasspartu;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getcUnrestrictedName() {
|
|
||||||
return Settings.getcUnrestrictedName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Boolean getEnablePasswordVerifier() {
|
|
||||||
return Settings.getEnablePasswordVerifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMaxNickLength() {
|
|
||||||
return Settings.getMaxNickLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMinNickLength() {
|
|
||||||
return Settings.getMinNickLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Array getLastLocationColumns() {
|
|
||||||
Array columns = null;
|
|
||||||
Array.set(columns, 0, Settings.getMySQLlastlocX);
|
|
||||||
Array.set(columns, 1, Settings.getMySQLlastlocY);
|
|
||||||
Array.set(columns, 2, Settings.getMySQLlastlocZ);
|
|
||||||
return columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Location getLastLocation(Player player) {
|
public static Location getLastLocation(Player player) {
|
||||||
try {
|
try {
|
||||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
|
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
||||||
|
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY() , auth.getQuitLocZ());
|
Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY() , auth.getQuitLocZ());
|
||||||
@ -145,30 +88,6 @@ public class API {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNickRegex() {
|
|
||||||
return Settings.getNickRegex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getPasswordMinLen() {
|
|
||||||
return Settings.getPasswordMinLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HashAlgorithm getPasswordHash() {
|
|
||||||
return Settings.getPasswordHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getRegistrationTimeout() {
|
|
||||||
return Settings.getRegistrationTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getSessionTimeout() {
|
|
||||||
return Settings.getSessionTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getUnloggedinGroup() {
|
|
||||||
return Settings.getUnloggedinGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) {
|
public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) {
|
||||||
try {
|
try {
|
||||||
player.getInventory().setContents(content);
|
player.getInventory().setContents(content);
|
||||||
@ -214,7 +133,7 @@ public class API {
|
|||||||
try {
|
try {
|
||||||
String name = playerName.toLowerCase();
|
String name = playerName.toLowerCase();
|
||||||
String hash = PasswordSecurity.getHash(Settings.getPasswordHash, password, name);
|
String hash = PasswordSecurity.getHash(Settings.getPasswordHash, password, name);
|
||||||
if (database.isAuthAvailable(name)) {
|
if (isRegistered(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PlayerAuth auth = new PlayerAuth(name, hash, "198.18.0.1", 0);
|
PlayerAuth auth = new PlayerAuth(name, hash, "198.18.0.1", 0);
|
||||||
|
@ -221,4 +221,12 @@ public class PlayerAuth {
|
|||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String s = "Player : " + nickname + " ! IP : " + ip + " ! LastLogin : " + lastLogin + " ! LastPosition : " + x + "," + y + "," + z + "," + world
|
||||||
|
+ " ! Email : " + email + " ! Hash : " + hash + " ! Salt : " + salt;
|
||||||
|
return s;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,24 +28,24 @@ public class PlayerCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addPlayer(PlayerAuth auth) {
|
public void addPlayer(PlayerAuth auth) {
|
||||||
cache.put(auth.getNickname(), auth);
|
cache.put(auth.getNickname().toLowerCase(), auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePlayer(PlayerAuth auth) {
|
public void updatePlayer(PlayerAuth auth) {
|
||||||
cache.remove(auth.getNickname());
|
cache.remove(auth.getNickname().toLowerCase());
|
||||||
cache.put(auth.getNickname(), auth);
|
cache.put(auth.getNickname().toLowerCase(), auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePlayer(String user) {
|
public void removePlayer(String user) {
|
||||||
cache.remove(user);
|
cache.remove(user.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAuthenticated(String user) {
|
public boolean isAuthenticated(String user) {
|
||||||
return cache.containsKey(user);
|
return cache.containsKey(user.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerAuth getAuth(String user) {
|
public PlayerAuth getAuth(String user) {
|
||||||
return cache.get(user);
|
return cache.get(user.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlayerCache getInstance() {
|
public static PlayerCache getInstance() {
|
||||||
|
@ -176,7 +176,7 @@ public class AdminCommand implements CommandExecutor {
|
|||||||
if (!args[1].contains(".")) {
|
if (!args[1].contains(".")) {
|
||||||
final CommandSender fSender = sender;
|
final CommandSender fSender = sender;
|
||||||
final String[] arguments = args;
|
final String[] arguments = args;
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PlayerAuth pAuth = null;
|
PlayerAuth pAuth = null;
|
||||||
@ -219,7 +219,7 @@ public class AdminCommand implements CommandExecutor {
|
|||||||
} else {
|
} else {
|
||||||
final CommandSender fSender = sender;
|
final CommandSender fSender = sender;
|
||||||
final String[] arguments = args;
|
final String[] arguments = args;
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String message = "[AuthMe] ";
|
String message = "[AuthMe] ";
|
||||||
@ -344,12 +344,16 @@ public class AdminCommand implements CommandExecutor {
|
|||||||
bannedPlayers.add(off.getName().toLowerCase());
|
bannedPlayers.add(off.getName().toLowerCase());
|
||||||
}
|
}
|
||||||
final List<String> bP = bannedPlayers;
|
final List<String> bP = bannedPlayers;
|
||||||
|
if (database instanceof Thread) {
|
||||||
|
database.purgeBanned(bP);
|
||||||
|
} else {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
database.purgeBanned(bP);
|
database.purgeBanned(bP);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else if (args[0].equalsIgnoreCase("spawn")) {
|
} else if (args[0].equalsIgnoreCase("spawn")) {
|
||||||
try {
|
try {
|
||||||
if (sender instanceof Player) {
|
if (sender instanceof Player) {
|
||||||
|
@ -172,6 +172,10 @@ public class EmailCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
final String finalhashnew = hashnew;
|
final String finalhashnew = hashnew;
|
||||||
final PlayerAuth finalauth = auth;
|
final PlayerAuth finalauth = auth;
|
||||||
|
if (data instanceof Thread) {
|
||||||
|
finalauth.setHash(hashnew);
|
||||||
|
data.updatePassword(auth);
|
||||||
|
} else {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -179,6 +183,7 @@ public class EmailCommand implements CommandExecutor {
|
|||||||
data.updatePassword(finalauth);
|
data.updatePassword(finalauth);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
plugin.mail.main(auth, thePass);
|
plugin.mail.main(auth, thePass);
|
||||||
player.sendMessage(m._("email_send"));
|
player.sendMessage(m._("email_send"));
|
||||||
} catch (NoSuchAlgorithmException ex) {
|
} catch (NoSuchAlgorithmException ex) {
|
||||||
|
@ -100,7 +100,7 @@ public class UnregisterCommand implements CommandExecutor {
|
|||||||
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name), delay);
|
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name), delay);
|
||||||
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id.getTaskId());
|
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id.getTaskId());
|
||||||
}
|
}
|
||||||
sched.runTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval));
|
sched.scheduleSyncDelayedTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval));
|
||||||
if(!Settings.unRegisteredGroup.isEmpty()){
|
if(!Settings.unRegisteredGroup.isEmpty()){
|
||||||
Utils.getInstance().setGroup(player, Utils.groupType.UNREGISTERED);
|
Utils.getInstance().setGroup(player, Utils.groupType.UNREGISTERED);
|
||||||
}
|
}
|
||||||
|
@ -153,8 +153,8 @@ private synchronized Connection getConnection3() throws SQLException {
|
|||||||
else {
|
else {
|
||||||
pconn = dataSource.getPooledConnection();
|
pconn = dataSource.getPooledConnection();
|
||||||
pconn.addConnectionEventListener(poolConnectionEventListener); }
|
pconn.addConnectionEventListener(poolConnectionEventListener); }
|
||||||
activeConnections++;
|
|
||||||
Connection conn = pconn.getConnection();
|
Connection conn = pconn.getConnection();
|
||||||
|
activeConnections++;
|
||||||
assertInnerState();
|
assertInnerState();
|
||||||
return conn; }
|
return conn; }
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSession(PlayerAuth auth) {
|
public synchronized boolean updateSession(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -307,7 +307,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int purgeDatabase(long until) {
|
public synchronized int purgeDatabase(long until) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -350,7 +350,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
public synchronized boolean updateQuitLoc(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -376,7 +376,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIps(String ip) {
|
public synchronized int getIps(String ip) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -405,7 +405,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateEmail(PlayerAuth auth) {
|
public synchronized boolean updateEmail(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -428,7 +428,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSalt(PlayerAuth auth) {
|
public synchronized boolean updateSalt(PlayerAuth auth) {
|
||||||
if (columnSalt.isEmpty()) {
|
if (columnSalt.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -497,7 +497,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -526,7 +526,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByIp(String ip) {
|
public synchronized List<String> getAllAuthsByIp(String ip) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -555,7 +555,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByEmail(String email) {
|
public synchronized List<String> getAllAuthsByEmail(String email) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -584,7 +584,7 @@ public class MySQLDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void purgeBanned(List<String> banned) {
|
public synchronized void purgeBanned(List<String> banned) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package uk.org.whoami.authme.datasource;
|
package uk.org.whoami.authme.datasource;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
@ -106,6 +102,7 @@ public class SqliteDataSource implements DataSource {
|
|||||||
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
|
rs = con.getMetaData().getColumns(null, null, tableName, lastlocWorld);
|
||||||
if (!rs.next()) {
|
if (!rs.next()) {
|
||||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -227,7 +227,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -285,7 +285,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -342,7 +342,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -399,7 +399,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -456,7 +456,7 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable()
|
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -831,12 +831,16 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
if(Settings.isSaveQuitLocationEnabled && data.isAuthAvailable(name)) {
|
if(Settings.isSaveQuitLocationEnabled && data.isAuthAvailable(name)) {
|
||||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(),loc.getBlockX(),loc.getBlockY(),loc.getBlockZ(),loc.getWorld().getName());
|
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(),loc.getBlockX(),loc.getBlockY(),loc.getBlockZ(),loc.getWorld().getName());
|
||||||
try {
|
try {
|
||||||
|
if (data instanceof Thread) {
|
||||||
|
data.updateQuitLoc(auth);
|
||||||
|
} else {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
data.updateQuitLoc(auth);
|
data.updateQuitLoc(auth);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} catch (NullPointerException npe) { }
|
} catch (NullPointerException npe) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -898,6 +902,10 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
if ((PlayerCache.getInstance().isAuthenticated(name)) && (!player.isDead()) &&
|
if ((PlayerCache.getInstance().isAuthenticated(name)) && (!player.isDead()) &&
|
||||||
(Settings.isSaveQuitLocationEnabled.booleanValue()) && data.isAuthAvailable(name)) {
|
(Settings.isSaveQuitLocationEnabled.booleanValue()) && data.isAuthAvailable(name)) {
|
||||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),loc.getWorld().getName());
|
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),loc.getWorld().getName());
|
||||||
|
try {
|
||||||
|
if (data instanceof Thread) {
|
||||||
|
data.updateQuitLoc(auth);
|
||||||
|
} else {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -905,6 +913,8 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} catch (NullPointerException npe) { }
|
||||||
|
}
|
||||||
|
|
||||||
if (LimboCache.getInstance().hasLimboPlayer(name))
|
if (LimboCache.getInstance().hasLimboPlayer(name))
|
||||||
{
|
{
|
||||||
@ -1181,12 +1191,18 @@ public class AuthMePlayerListener implements Listener {
|
|||||||
if (Spawn.getInstance().getLocation() != null && Spawn.getInstance().getLocation().getWorld().equals(player.getWorld()))
|
if (Spawn.getInstance().getLocation() != null && Spawn.getInstance().getLocation().getWorld().equals(player.getWorld()))
|
||||||
spawn = Spawn.getInstance().getLocation();
|
spawn = Spawn.getInstance().getLocation();
|
||||||
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ(),spawn.getWorld().getName());
|
final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ(),spawn.getWorld().getName());
|
||||||
|
try {
|
||||||
|
if (data instanceof Thread) {
|
||||||
|
data.updateQuitLoc(auth);
|
||||||
|
} else {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
data.updateQuitLoc(auth);
|
data.updateQuitLoc(auth);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
} catch (NullPointerException npe) { }
|
||||||
event.setRespawnLocation(spawn);
|
event.setRespawnLocation(spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||||
|
|
||||||
import uk.org.whoami.authme.AuthMe;
|
import uk.org.whoami.authme.AuthMe;
|
||||||
import uk.org.whoami.authme.ConsoleLogger;
|
|
||||||
|
|
||||||
public class BungeeCordMessage implements PluginMessageListener {
|
public class BungeeCordMessage implements PluginMessageListener {
|
||||||
|
|
||||||
@ -24,7 +23,6 @@ public class BungeeCordMessage implements PluginMessageListener {
|
|||||||
try {
|
try {
|
||||||
final DataInputStream in = new DataInputStream(new ByteArrayInputStream(message));
|
final DataInputStream in = new DataInputStream(new ByteArrayInputStream(message));
|
||||||
if (in.readUTF().equals("IP")) { //We need only the IP channel
|
if (in.readUTF().equals("IP")) { //We need only the IP channel
|
||||||
ConsoleLogger.info("PluginMessage send to " + player.getName() + " , the message was : " + message.toString());
|
|
||||||
plugin.realIp.put(player.getName().toLowerCase(), in.readUTF()); //Put the IP (only the ip not the port) in the hashmap
|
plugin.realIp.put(player.getName().toLowerCase(), in.readUTF()); //Put the IP (only the ip not the port) in the hashmap
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
@ -28,6 +28,8 @@ import javax.crypto.Mac;
|
|||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import uk.org.whoami.authme.AuthMe;
|
import uk.org.whoami.authme.AuthMe;
|
||||||
|
import uk.org.whoami.authme.security.pbkdf2.PBKDF2Engine;
|
||||||
|
import uk.org.whoami.authme.security.pbkdf2.PBKDF2Parameters;
|
||||||
import uk.org.whoami.authme.settings.Settings;
|
import uk.org.whoami.authme.settings.Settings;
|
||||||
|
|
||||||
public class PasswordSecurity {
|
public class PasswordSecurity {
|
||||||
@ -106,6 +108,13 @@ public class PasswordSecurity {
|
|||||||
return getSHA1(salt.concat(getSHA1(salt.concat(getSHA1(message)))));
|
return getSHA1(salt.concat(getSHA1(salt.concat(getSHA1(message)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getPBKDF2(String password, String salt) throws NoSuchAlgorithmException {
|
||||||
|
String result = "pbkdf2_sha256$10000$"+salt+"$";
|
||||||
|
PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000);
|
||||||
|
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||||
|
return result + engine.deriveKey(password,57).toString();
|
||||||
|
}
|
||||||
|
|
||||||
private static String createSalt(int length) throws NoSuchAlgorithmException {
|
private static String createSalt(int length) throws NoSuchAlgorithmException {
|
||||||
byte[] msg = new byte[40];
|
byte[] msg = new byte[40];
|
||||||
rnd.nextBytes(msg);
|
rnd.nextBytes(msg);
|
||||||
@ -226,6 +235,9 @@ public class PasswordSecurity {
|
|||||||
return getSHA512(password);
|
return getSHA512(password);
|
||||||
case DOUBLEMD5:
|
case DOUBLEMD5:
|
||||||
return getMD5(getMD5(password));
|
return getMD5(getMD5(password));
|
||||||
|
case PBKDF2:
|
||||||
|
String saltpbkdf2 = createSalt(12);
|
||||||
|
return getPBKDF2(password, saltpbkdf2);
|
||||||
default:
|
default:
|
||||||
throw new NoSuchAlgorithmException("Unknown hash algorithm");
|
throw new NoSuchAlgorithmException("Unknown hash algorithm");
|
||||||
}
|
}
|
||||||
@ -237,24 +249,24 @@ public class PasswordSecurity {
|
|||||||
return checkHash.phpbb_check_hash(password, hash);
|
return checkHash.phpbb_check_hash(password, hash);
|
||||||
}
|
}
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.WBB3) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.WBB3) {
|
||||||
String saltwbb3 = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(getWBB3(password, saltwbb3));
|
return hash.equals(getWBB3(password, salt));
|
||||||
}
|
}
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.IPB3) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.IPB3) {
|
||||||
String saltipb = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(getSaltedIPB3(password, saltipb));
|
return hash.equals(getSaltedIPB3(password, salt));
|
||||||
}
|
}
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.BCRYPT) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.BCRYPT) {
|
||||||
String saltbcrypt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(BCrypt.hashpw(password, saltbcrypt));
|
return hash.equals(BCrypt.hashpw(password, salt));
|
||||||
}
|
}
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.PHPFUSION) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.PHPFUSION) {
|
||||||
String saltfusion = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(getPhPFusion(password, saltfusion));
|
return hash.equals(getPhPFusion(password, salt));
|
||||||
}
|
}
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MYBB) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MYBB) {
|
||||||
String saltmybb = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(getSaltedMyBB(password, saltmybb));
|
return hash.equals(getSaltedMyBB(password, salt));
|
||||||
}
|
}
|
||||||
if(Settings.getPasswordHash == HashAlgorithm.SMF)
|
if(Settings.getPasswordHash == HashAlgorithm.SMF)
|
||||||
return hash.equals(getSHA1(playername.toLowerCase() + password));
|
return hash.equals(getSHA1(playername.toLowerCase() + password));
|
||||||
@ -265,15 +277,23 @@ public class PasswordSecurity {
|
|||||||
if(Settings.getPasswordHash == HashAlgorithm.DOUBLEMD5)
|
if(Settings.getPasswordHash == HashAlgorithm.DOUBLEMD5)
|
||||||
return hash.equals(getMD5(getMD5(password)));
|
return hash.equals(getMD5(getMD5(password)));
|
||||||
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.SALTED2MD5) {
|
if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.SALTED2MD5) {
|
||||||
String salt2md5 = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
String salt = AuthMe.getInstance().database.getAuth(playername).getSalt();
|
||||||
return hash.equals(getMD5(getMD5(password) + salt2md5));
|
return hash.equals(getMD5(getMD5(password) + salt));
|
||||||
}
|
}
|
||||||
if(Settings.getPasswordHash == HashAlgorithm.JOOMLA) {
|
if(Settings.getPasswordHash == HashAlgorithm.JOOMLA) {
|
||||||
String saltj = hash.split(":")[1];
|
String salt = hash.split(":")[1];
|
||||||
return hash.equals(getMD5(password + saltj) + ":" + saltj);
|
return hash.equals(getMD5(password + salt) + ":" + salt);
|
||||||
}
|
}
|
||||||
if(Settings.getPasswordHash == HashAlgorithm.SHA512)
|
if(Settings.getPasswordHash == HashAlgorithm.SHA512)
|
||||||
return hash.equals(getSHA512(password));
|
return hash.equals(getSHA512(password));
|
||||||
|
if(Settings.getPasswordHash == HashAlgorithm.PBKDF2) {
|
||||||
|
String[] line = hash.split("\\$");
|
||||||
|
String salt = line[2];
|
||||||
|
String derivedKey = line[3];
|
||||||
|
PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000, derivedKey.getBytes());
|
||||||
|
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||||
|
return engine.verifyKey(password);
|
||||||
|
}
|
||||||
// PlainText Password
|
// PlainText Password
|
||||||
if(hash.length() < 32 )
|
if(hash.length() < 32 )
|
||||||
return hash.equals(password);
|
return hash.equals(password);
|
||||||
@ -336,7 +356,7 @@ public class PasswordSecurity {
|
|||||||
public enum HashAlgorithm {
|
public enum HashAlgorithm {
|
||||||
|
|
||||||
MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, PLAINTEXT, MYBB, IPB3, PHPFUSION, SMF, XFSHA1,
|
MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, PLAINTEXT, MYBB, IPB3, PHPFUSION, SMF, XFSHA1,
|
||||||
XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5
|
XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5, PBKDF2
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
137
src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java
Normal file
137
src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Free auxiliary functions. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class BinTools
|
||||||
|
{
|
||||||
|
public static final String hex = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple binary-to-hexadecimal conversion.
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* Input bytes. May be <code>null</code>.
|
||||||
|
* @return Hexadecimal representation of b. Uppercase A-F, two characters
|
||||||
|
* per byte. Empty string on <code>null</code> input.
|
||||||
|
*/
|
||||||
|
public static String bin2hex(final byte[] b)
|
||||||
|
{
|
||||||
|
if (b == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuffer sb = new StringBuffer(2 * b.length);
|
||||||
|
for (int i = 0; i < b.length; i++)
|
||||||
|
{
|
||||||
|
int v = (256 + b[i]) % 256;
|
||||||
|
sb.append(hex.charAt((v / 16) & 15));
|
||||||
|
sb.append(hex.charAt((v % 16) & 15));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert hex string to array of bytes.
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
* String containing hexadecimal digits. May be <code>null</code>.
|
||||||
|
* On odd length leading zero will be assumed.
|
||||||
|
* @return Array on bytes, non-<code>null</code>.
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* when string contains non-hex character
|
||||||
|
*/
|
||||||
|
public static byte[] hex2bin(final String s)
|
||||||
|
{
|
||||||
|
String m = s;
|
||||||
|
if (s == null)
|
||||||
|
{
|
||||||
|
// Allow empty input string.
|
||||||
|
m = "";
|
||||||
|
}
|
||||||
|
else if (s.length() % 2 != 0)
|
||||||
|
{
|
||||||
|
// Assume leading zero for odd string length
|
||||||
|
m = "0" + s;
|
||||||
|
}
|
||||||
|
byte r[] = new byte[m.length() / 2];
|
||||||
|
for (int i = 0, n = 0; i < m.length(); n++)
|
||||||
|
{
|
||||||
|
char h = m.charAt(i++);
|
||||||
|
char l = m.charAt(i++);
|
||||||
|
r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert hex digit to numerical value.
|
||||||
|
*
|
||||||
|
* @param c
|
||||||
|
* 0-9, a-f, A-F allowd.
|
||||||
|
* @return 0-15
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* on non-hex character
|
||||||
|
*/
|
||||||
|
public static int hex2bin(char c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
return (c - '0');
|
||||||
|
}
|
||||||
|
if (c >= 'A' && c <= 'F')
|
||||||
|
{
|
||||||
|
return (c - 'A' + 10);
|
||||||
|
}
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
{
|
||||||
|
return (c - 'a' + 10);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input string may only contain hex digits, but found '" + c
|
||||||
|
+ "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
byte b[] = new byte[256];
|
||||||
|
byte bb = 0;
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
b[i] = bb++;
|
||||||
|
}
|
||||||
|
String s = bin2hex(b);
|
||||||
|
byte c[] = hex2bin(s);
|
||||||
|
String t = bin2hex(c);
|
||||||
|
if (!s.equals(t))
|
||||||
|
{
|
||||||
|
throw new AssertionError("Mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
||||||
|
*
|
||||||
|
* <hr />
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class MacBasedPRF implements PRF
|
||||||
|
{
|
||||||
|
protected Mac mac;
|
||||||
|
|
||||||
|
protected int hLen;
|
||||||
|
|
||||||
|
protected String macAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Mac-based Pseudo Random Function.
|
||||||
|
*
|
||||||
|
* @param macAlgorithm
|
||||||
|
* Mac algorithm to use, i.e. HMacSHA1 or HMacMD5.
|
||||||
|
*/
|
||||||
|
public MacBasedPRF(String macAlgorithm)
|
||||||
|
{
|
||||||
|
this.macAlgorithm = macAlgorithm;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mac = Mac.getInstance(macAlgorithm);
|
||||||
|
hLen = mac.getMacLength();
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MacBasedPRF(String macAlgorithm, String provider)
|
||||||
|
{
|
||||||
|
this.macAlgorithm = macAlgorithm;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mac = Mac.getInstance(macAlgorithm, provider);
|
||||||
|
hLen = mac.getMacLength();
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (NoSuchProviderException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] doFinal(byte[] M)
|
||||||
|
{
|
||||||
|
byte[] r = mac.doFinal(M);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHLen()
|
||||||
|
{
|
||||||
|
return hLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(byte[] P)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mac.init(new SecretKeySpec(P, macAlgorithm));
|
||||||
|
}
|
||||||
|
catch (InvalidKeyException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public interface PBKDF2
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||||
|
* Desired key length defaults to Pseudo Random Function block size.
|
||||||
|
*
|
||||||
|
* @param inputPassword
|
||||||
|
* Candidate password to compute the derived key for.
|
||||||
|
* @return internal byte array
|
||||||
|
*/
|
||||||
|
public abstract byte[] deriveKey(String inputPassword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
||||||
|
*
|
||||||
|
* @param inputPassword
|
||||||
|
* Candidate password to compute the derived key for.
|
||||||
|
* @param dkLen
|
||||||
|
* Specify desired key length
|
||||||
|
* @return internal byte array
|
||||||
|
*/
|
||||||
|
public abstract byte[] deriveKey(String inputPassword, int dkLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert String-based input to internal byte arrays, then invoke PBKDF2
|
||||||
|
* and verify result against the reference data that is supplied in the
|
||||||
|
* PBKDF2Parameters.
|
||||||
|
*
|
||||||
|
* @param inputPassword
|
||||||
|
* Candidate password to compute the derived key for.
|
||||||
|
* @return <code>true</code> password match; <code>false</code>
|
||||||
|
* incorrect password
|
||||||
|
*/
|
||||||
|
public abstract boolean verifyKey(String inputPassword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow reading of configured parameters.
|
||||||
|
*
|
||||||
|
* @return Currently set parameters.
|
||||||
|
*/
|
||||||
|
public abstract PBKDF2Parameters getParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow setting of configured parameters.
|
||||||
|
*
|
||||||
|
* @param parameters
|
||||||
|
*/
|
||||||
|
public abstract void setParameters(PBKDF2Parameters parameters);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get currently set Pseudo Random Function.
|
||||||
|
*
|
||||||
|
* @return Currently set Pseudo Random Function
|
||||||
|
*/
|
||||||
|
public abstract PRF getPseudoRandomFunction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does
|
||||||
|
* init this object using the supplied candidate password. If this is
|
||||||
|
* undesired, one has to override getPRF.
|
||||||
|
*
|
||||||
|
* @param prf
|
||||||
|
* Pseudo Random Function to set.
|
||||||
|
*/
|
||||||
|
public abstract void setPseudoRandomFunction(PRF prf);
|
||||||
|
}
|
@ -0,0 +1,401 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
||||||
|
* <p>
|
||||||
|
* Version 2.0
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* PBKDF2 (P, S, c, dkLen)
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Options:
|
||||||
|
* <ul>
|
||||||
|
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
||||||
|
* of the pseudorandom function output). PRF is pluggable.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Input:
|
||||||
|
* <ul>
|
||||||
|
* <li>P password, an octet string</li>
|
||||||
|
* <li>S salt, an octet string</li>
|
||||||
|
* <li>c iteration count, a positive integer</li>
|
||||||
|
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
||||||
|
* at most (2^32 - 1) * hLen</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Output:
|
||||||
|
* <ul>
|
||||||
|
* <li>DK derived key, a dkLen-octet string</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <hr />
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class PBKDF2Engine implements PBKDF2
|
||||||
|
{
|
||||||
|
protected PBKDF2Parameters parameters;
|
||||||
|
|
||||||
|
protected PRF prf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for PBKDF2 implementation object. PBKDF2 parameters must be
|
||||||
|
* passed later.
|
||||||
|
*/
|
||||||
|
public PBKDF2Engine()
|
||||||
|
{
|
||||||
|
this.parameters = null;
|
||||||
|
prf = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||||
|
* passed so that this implementation knows iteration count, method to use
|
||||||
|
* and String encoding.
|
||||||
|
*
|
||||||
|
* @param parameters
|
||||||
|
* Data holder for iteration count, method to use et cetera.
|
||||||
|
*/
|
||||||
|
public PBKDF2Engine(PBKDF2Parameters parameters)
|
||||||
|
{
|
||||||
|
this.parameters = parameters;
|
||||||
|
prf = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
||||||
|
* passed so that this implementation knows iteration count, method to use
|
||||||
|
* and String encoding.
|
||||||
|
*
|
||||||
|
* @param parameters
|
||||||
|
* Data holder for iteration count, method to use et cetera.
|
||||||
|
* @param prf
|
||||||
|
* Supply customer Pseudo Random Function.
|
||||||
|
*/
|
||||||
|
public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf)
|
||||||
|
{
|
||||||
|
this.parameters = parameters;
|
||||||
|
this.prf = prf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] deriveKey(String inputPassword)
|
||||||
|
{
|
||||||
|
return deriveKey(inputPassword, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] deriveKey(String inputPassword, int dkLen)
|
||||||
|
{
|
||||||
|
byte[] r = null;
|
||||||
|
byte P[] = null;
|
||||||
|
String charset = parameters.getHashCharset();
|
||||||
|
if (inputPassword == null)
|
||||||
|
{
|
||||||
|
inputPassword = "";
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (charset == null)
|
||||||
|
{
|
||||||
|
P = inputPassword.getBytes();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P = inputPassword.getBytes(charset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
assertPRF(P);
|
||||||
|
if (dkLen == 0)
|
||||||
|
{
|
||||||
|
dkLen = prf.getHLen();
|
||||||
|
}
|
||||||
|
r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(),
|
||||||
|
dkLen);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verifyKey(String inputPassword)
|
||||||
|
{
|
||||||
|
byte[] referenceKey = getParameters().getDerivedKey();
|
||||||
|
if (referenceKey == null || referenceKey.length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
|
||||||
|
|
||||||
|
if (inputKey == null || inputKey.length != referenceKey.length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inputKey.length; i++)
|
||||||
|
{
|
||||||
|
if (inputKey[i] != referenceKey[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method. Default implementation is (H)MAC-based. To be overridden
|
||||||
|
* in derived classes.
|
||||||
|
*
|
||||||
|
* @param P
|
||||||
|
* User-supplied candidate password as array of bytes.
|
||||||
|
*/
|
||||||
|
protected void assertPRF(byte[] P)
|
||||||
|
{
|
||||||
|
if (prf == null)
|
||||||
|
{
|
||||||
|
prf = new MacBasedPRF(parameters.getHashAlgorithm());
|
||||||
|
}
|
||||||
|
prf.init(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PRF getPseudoRandomFunction()
|
||||||
|
{
|
||||||
|
return prf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Password Based Key Derivation Function 2.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
|
||||||
|
* @param prf
|
||||||
|
* Pseudo Random Function (i.e. HmacSHA1)
|
||||||
|
* @param S
|
||||||
|
* Salt as array of bytes. <code>null</code> means no salt.
|
||||||
|
* @param c
|
||||||
|
* Iteration count (see RFC 2898 4.2)
|
||||||
|
* @param dkLen
|
||||||
|
* desired length of derived key.
|
||||||
|
* @return internal byte array
|
||||||
|
*/
|
||||||
|
protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen)
|
||||||
|
{
|
||||||
|
if (S == null)
|
||||||
|
{
|
||||||
|
S = new byte[0];
|
||||||
|
}
|
||||||
|
int hLen = prf.getHLen();
|
||||||
|
int l = ceil(dkLen, hLen);
|
||||||
|
int r = dkLen - (l - 1) * hLen;
|
||||||
|
byte T[] = new byte[l * hLen];
|
||||||
|
int ti_offset = 0;
|
||||||
|
for (int i = 1; i <= l; i++)
|
||||||
|
{
|
||||||
|
_F(T, ti_offset, prf, S, c, i);
|
||||||
|
ti_offset += hLen;
|
||||||
|
}
|
||||||
|
if (r < hLen)
|
||||||
|
{
|
||||||
|
// Incomplete last block
|
||||||
|
byte DK[] = new byte[dkLen];
|
||||||
|
System.arraycopy(T, 0, DK, 0, dkLen);
|
||||||
|
return DK;
|
||||||
|
}
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integer division with ceiling function.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 2.</a>
|
||||||
|
* @param a
|
||||||
|
* @param b
|
||||||
|
* @return ceil(a/b)
|
||||||
|
*/
|
||||||
|
protected int ceil(int a, int b)
|
||||||
|
{
|
||||||
|
int m = 0;
|
||||||
|
if (a % b > 0)
|
||||||
|
{
|
||||||
|
m = 1;
|
||||||
|
}
|
||||||
|
return a / b + m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function F.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
|
||||||
|
* @param dest
|
||||||
|
* Destination byte buffer
|
||||||
|
* @param offset
|
||||||
|
* Offset into destination byte buffer
|
||||||
|
* @param prf
|
||||||
|
* Pseudo Random Function
|
||||||
|
* @param S
|
||||||
|
* Salt as array of bytes
|
||||||
|
* @param c
|
||||||
|
* Iteration count
|
||||||
|
* @param blockIndex
|
||||||
|
*/
|
||||||
|
protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c,
|
||||||
|
int blockIndex)
|
||||||
|
{
|
||||||
|
int hLen = prf.getHLen();
|
||||||
|
byte U_r[] = new byte[hLen];
|
||||||
|
|
||||||
|
// U0 = S || INT (i);
|
||||||
|
byte U_i[] = new byte[S.length + 4];
|
||||||
|
System.arraycopy(S, 0, U_i, 0, S.length);
|
||||||
|
INT(U_i, S.length, blockIndex);
|
||||||
|
|
||||||
|
for (int i = 0; i < c; i++)
|
||||||
|
{
|
||||||
|
U_i = prf.doFinal(U_i);
|
||||||
|
xor(U_r, U_i);
|
||||||
|
}
|
||||||
|
System.arraycopy(U_r, 0, dest, offset, hLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
||||||
|
* buffer must be same length or less than source buffer.
|
||||||
|
*
|
||||||
|
* @param dest
|
||||||
|
* @param src
|
||||||
|
*/
|
||||||
|
protected void xor(byte[] dest, byte[] src)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < dest.length; i++)
|
||||||
|
{
|
||||||
|
dest[i] ^= src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Four-octet encoding of the integer i, most significant octet first.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step 3.</a>
|
||||||
|
* @param dest
|
||||||
|
* @param offset
|
||||||
|
* @param i
|
||||||
|
*/
|
||||||
|
protected void INT(byte[] dest, int offset, int i)
|
||||||
|
{
|
||||||
|
dest[offset + 0] = (byte) (i / (256 * 256 * 256));
|
||||||
|
dest[offset + 1] = (byte) (i / (256 * 256));
|
||||||
|
dest[offset + 2] = (byte) (i / (256));
|
||||||
|
dest[offset + 3] = (byte) (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PBKDF2Parameters getParameters()
|
||||||
|
{
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameters(PBKDF2Parameters parameters)
|
||||||
|
{
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPseudoRandomFunction(PRF prf)
|
||||||
|
{
|
||||||
|
this.prf = prf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience client function. Convert supplied password with random 8-byte
|
||||||
|
* salt and 1000 iterations using HMacSHA1. Assume that password is in
|
||||||
|
* ISO-8559-1 encoding. Output result as
|
||||||
|
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
||||||
|
* encoding.
|
||||||
|
*
|
||||||
|
* Example: Password "password" (without the quotes) leads to
|
||||||
|
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* Supply the password as argument.
|
||||||
|
* @throws IOException
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws IOException,
|
||||||
|
NoSuchAlgorithmException
|
||||||
|
{
|
||||||
|
String password = "password";
|
||||||
|
String candidate = null;
|
||||||
|
PBKDF2Formatter formatter = new PBKDF2HexFormatter();
|
||||||
|
|
||||||
|
if (args.length >= 1)
|
||||||
|
{
|
||||||
|
password = args[0];
|
||||||
|
}
|
||||||
|
if (args.length >= 2)
|
||||||
|
{
|
||||||
|
candidate = args[1];
|
||||||
|
}
|
||||||
|
if (candidate == null)
|
||||||
|
{
|
||||||
|
// Creation mode
|
||||||
|
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||||
|
byte[] salt = new byte[8];
|
||||||
|
sr.nextBytes(salt);
|
||||||
|
int iterations = 1000;
|
||||||
|
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1",
|
||||||
|
salt, iterations);
|
||||||
|
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||||
|
p.setDerivedKey(e.deriveKey(password));
|
||||||
|
candidate = formatter.toString(p);
|
||||||
|
System.out.println(candidate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Verification mode
|
||||||
|
PBKDF2Parameters p = new PBKDF2Parameters();
|
||||||
|
p.setHashAlgorithm("HmacSHA1");
|
||||||
|
p.setHashCharset("ISO-8859-1");
|
||||||
|
if (formatter.fromString(p, candidate))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Candidate data does not have correct format (\""
|
||||||
|
+ candidate + "\")");
|
||||||
|
}
|
||||||
|
PBKDF2Engine e = new PBKDF2Engine(p);
|
||||||
|
boolean verifyOK = e.verifyKey(password);
|
||||||
|
System.out.println(verifyOK ? "OK" : "FAIL");
|
||||||
|
System.exit(verifyOK ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public interface PBKDF2Formatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert parameters to String.
|
||||||
|
*
|
||||||
|
* @param p
|
||||||
|
* Parameters object to output.
|
||||||
|
* @return String representation
|
||||||
|
*/
|
||||||
|
public abstract String toString(PBKDF2Parameters p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert String to parameters. Depending on actual implementation, it may
|
||||||
|
* be required to set further fields externally.
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
* String representation of parameters to decode.
|
||||||
|
* @return <code>false</code> syntax OK, <code>true</code> some syntax
|
||||||
|
* issue.
|
||||||
|
*/
|
||||||
|
public abstract boolean fromString(PBKDF2Parameters p, String s);
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class PBKDF2HexFormatter implements PBKDF2Formatter
|
||||||
|
{
|
||||||
|
public boolean fromString(PBKDF2Parameters p, String s)
|
||||||
|
{
|
||||||
|
if (p == null || s == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] p123 = s.split(":");
|
||||||
|
if (p123 == null || p123.length != 3)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte salt[] = BinTools.hex2bin(p123[0]);
|
||||||
|
int iterationCount = Integer.parseInt(p123[1]);
|
||||||
|
byte bDK[] = BinTools.hex2bin(p123[2]);
|
||||||
|
|
||||||
|
p.setSalt(salt);
|
||||||
|
p.setIterationCount(iterationCount);
|
||||||
|
p.setDerivedKey(bDK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(PBKDF2Parameters p)
|
||||||
|
{
|
||||||
|
String s = BinTools.bin2hex(p.getSalt()) + ":"
|
||||||
|
+ String.valueOf(p.getIterationCount()) + ":"
|
||||||
|
+ BinTools.bin2hex(p.getDerivedKey());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Parameter data holder for PBKDF2 configuration.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <hr />
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class PBKDF2Parameters
|
||||||
|
{
|
||||||
|
protected byte[] salt;
|
||||||
|
|
||||||
|
protected int iterationCount;
|
||||||
|
|
||||||
|
protected String hashAlgorithm;
|
||||||
|
|
||||||
|
protected String hashCharset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The derived key is actually only a convenience to store a reference
|
||||||
|
* derived key. It is not used during computation.
|
||||||
|
*/
|
||||||
|
protected byte[] derivedKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. Defaults to <code>null</code> for byte arrays, UTF-8 as
|
||||||
|
* character set and 1000 for iteration count.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public PBKDF2Parameters()
|
||||||
|
{
|
||||||
|
this.hashAlgorithm = null;
|
||||||
|
this.hashCharset = "UTF-8";
|
||||||
|
this.salt = null;
|
||||||
|
this.iterationCount = 1000;
|
||||||
|
this.derivedKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param hashAlgorithm
|
||||||
|
* for example HMacSHA1 or HMacMD5
|
||||||
|
* @param hashCharset
|
||||||
|
* for example UTF-8
|
||||||
|
* @param salt
|
||||||
|
* Salt as byte array, may be <code>null</code> (not
|
||||||
|
* recommended)
|
||||||
|
* @param iterationCount
|
||||||
|
* Number of iterations to execute. Recommended value 1000.
|
||||||
|
*/
|
||||||
|
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||||
|
byte[] salt, int iterationCount)
|
||||||
|
{
|
||||||
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
|
this.hashCharset = hashCharset;
|
||||||
|
this.salt = salt;
|
||||||
|
this.iterationCount = iterationCount;
|
||||||
|
this.derivedKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param hashAlgorithm
|
||||||
|
* for example HMacSHA1 or HMacMD5
|
||||||
|
* @param hashCharset
|
||||||
|
* for example UTF-8
|
||||||
|
* @param salt
|
||||||
|
* Salt as byte array, may be <code>null</code> (not
|
||||||
|
* recommended)
|
||||||
|
* @param iterationCount
|
||||||
|
* Number of iterations to execute. Recommended value 1000.
|
||||||
|
* @param derivedKey
|
||||||
|
* Convenience data holder, not used during computation.
|
||||||
|
*/
|
||||||
|
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
||||||
|
byte[] salt, int iterationCount, byte[] derivedKey)
|
||||||
|
{
|
||||||
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
|
this.hashCharset = hashCharset;
|
||||||
|
this.salt = salt;
|
||||||
|
this.iterationCount = iterationCount;
|
||||||
|
this.derivedKey = derivedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIterationCount()
|
||||||
|
{
|
||||||
|
return iterationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIterationCount(int iterationCount)
|
||||||
|
{
|
||||||
|
this.iterationCount = iterationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSalt()
|
||||||
|
{
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalt(byte[] salt)
|
||||||
|
{
|
||||||
|
this.salt = salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getDerivedKey()
|
||||||
|
{
|
||||||
|
return derivedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDerivedKey(byte[] derivedKey)
|
||||||
|
{
|
||||||
|
this.derivedKey = derivedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashAlgorithm()
|
||||||
|
{
|
||||||
|
return hashAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashAlgorithm(String hashAlgorithm)
|
||||||
|
{
|
||||||
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashCharset()
|
||||||
|
{
|
||||||
|
return hashCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHashCharset(String hashCharset)
|
||||||
|
{
|
||||||
|
this.hashCharset = hashCharset;
|
||||||
|
}
|
||||||
|
}
|
60
src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java
Normal file
60
src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package uk.org.whoami.authme.security.pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A free Java implementation of Password Based Key Derivation Function 2 as
|
||||||
|
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This library is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
* details.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* For Details, see <a
|
||||||
|
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Matthias Gärtner
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public interface PRF
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initialize this instance with the user-supplied password.
|
||||||
|
*
|
||||||
|
* @param P
|
||||||
|
* The password supplied as array of bytes. It is the caller's
|
||||||
|
* task to convert String passwords to bytes as appropriate.
|
||||||
|
*/
|
||||||
|
public void init(byte[] P);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pseudo Random Function
|
||||||
|
*
|
||||||
|
* @param M
|
||||||
|
* Input data/message etc. Together with any data supplied during
|
||||||
|
* initilization.
|
||||||
|
* @return Random bytes of hLen length.
|
||||||
|
*/
|
||||||
|
public byte[] doFinal(byte[] M);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query block size of underlying algorithm/mechanism.
|
||||||
|
*
|
||||||
|
* @return block size
|
||||||
|
*/
|
||||||
|
public int getHLen();
|
||||||
|
}
|
@ -299,7 +299,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSession(PlayerAuth auth) {
|
public synchronized boolean updateSession(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -323,7 +323,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int purgeDatabase(long until) {
|
public synchronized int purgeDatabase(long until) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -366,7 +366,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
public synchronized boolean updateQuitLoc(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -392,7 +392,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIps(String ip) {
|
public synchronized int getIps(String ip) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -421,7 +421,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateEmail(PlayerAuth auth) {
|
public synchronized boolean updateEmail(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -444,7 +444,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateSalt(PlayerAuth auth) {
|
public synchronized boolean updateSalt(PlayerAuth auth) {
|
||||||
if (columnSalt.isEmpty()) {
|
if (columnSalt.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -513,7 +513,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByName(PlayerAuth auth) {
|
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -542,7 +542,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByIp(String ip) {
|
public synchronized List<String> getAllAuthsByIp(String ip) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -571,7 +571,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAllAuthsByEmail(String email) {
|
public synchronized List<String> getAllAuthsByEmail(String email) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@ -600,7 +600,7 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void purgeBanned(List<String> banned) {
|
public synchronized void purgeBanned(List<String> banned) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement pst = null;
|
PreparedStatement pst = null;
|
||||||
try {
|
try {
|
||||||
@ -617,4 +617,35 @@ public class MySQLThread extends Thread implements DataSource {
|
|||||||
close(con);
|
close(con);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* public synchronized boolean makeSureConnectionIsReady() {
|
||||||
|
try {
|
||||||
|
conPool.getValidConnection();
|
||||||
|
return true;
|
||||||
|
} catch (TimeoutException te) {
|
||||||
|
try {
|
||||||
|
reconnect();
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
return false;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void reconnect() throws ClassNotFoundException, SQLException, TimeoutException {
|
||||||
|
conPool.dispose();
|
||||||
|
Class.forName("com.mysql.jdbc.Driver");
|
||||||
|
MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
|
||||||
|
dataSource.setDatabaseName(database);
|
||||||
|
dataSource.setServerName(host);
|
||||||
|
dataSource.setPort(Integer.parseInt(port));
|
||||||
|
dataSource.setUser(username);
|
||||||
|
dataSource.setPassword(password);
|
||||||
|
conPool = new MiniConnectionPoolManager(dataSource, 10);
|
||||||
|
ConsoleLogger.info("Connection pool reconnected");
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,7 @@ public class SQLiteThread extends Thread implements DataSource {
|
|||||||
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
+ "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';");
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
|
rs = con.getMetaData().getColumns(null, null, tableName, lastlocWorld);
|
||||||
if (!rs.next()) {
|
if (!rs.next()) {
|
||||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ no_perm: '&cSem permissao!'
|
|||||||
error: '&fOcorreu um erro de sistema, por favor reporte ao ADM.'
|
error: '&fOcorreu um erro de sistema, por favor reporte ao ADM.'
|
||||||
login_msg: '&cPara entrar digite: "/login password"'
|
login_msg: '&cPara entrar digite: "/login password"'
|
||||||
reg_msg: '&cPara registrar um nick digite: "/register senha senha"'
|
reg_msg: '&cPara registrar um nick digite: "/register senha senha"'
|
||||||
reg_email_msg: '&cPlease register with "/register <email> <confirmEmail>"'
|
reg_email_msg: '&cPara registrar um nick digite: "/register <e-mail> <e-mail>"'
|
||||||
usage_unreg: '&cPara desregistrar digite: /unregister senha'
|
usage_unreg: '&cPara desregistrar digite: /unregister senha'
|
||||||
pwd_changed: '&cSenha modificada!'
|
pwd_changed: '&cSenha modificada!'
|
||||||
user_unknown: '&cNome de usuario nao existe. Verifique.'
|
user_unknown: '&cNome de usuario nao existe. Verifique.'
|
||||||
@ -29,23 +29,23 @@ registered: '&cRegistrado com sucesso!'
|
|||||||
pass_len: '&fSenha muito curta.'
|
pass_len: '&fSenha muito curta.'
|
||||||
reload: '&fAuthMe Recarregado.'
|
reload: '&fAuthMe Recarregado.'
|
||||||
timeout: '&fDemorou....'
|
timeout: '&fDemorou....'
|
||||||
name_len: '&cYour nickname is too Short or too long'
|
name_len: '&cSeu nome de usuário é muito longo'
|
||||||
regex: '&cYour nickname contains illegal characters. Allowed chars: REG_EX'
|
regex: '&cSeu nome de usuário tem caracteres ilegais. Permitido: REG_EX'
|
||||||
add_email: '&cPlease add your email with : /email add yourEmail confirmEmail'
|
add_email: '&cAdicione seu e-mail, digite: /email add e-mail e-mail'
|
||||||
bad_database_email: '[AuthMe] This /email command only available with MySQL and SQLite, contact an Admin'
|
bad_database_email: '[AuthMe] Comando /email disponibilizado apenas com MySQL e SQLite, contate um Admin'
|
||||||
recovery_email: '&cForgot your password? Please use /email recovery <yourEmail>'
|
recovery_email: '&cEsqueceu sua senha? Digite /email recovery <e-mail>'
|
||||||
usage_captcha: '&cUsage: /captcha <theCaptcha>'
|
usage_captcha: '&cDigite: /captcha <theCaptcha>'
|
||||||
wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
wrong_captcha: '&Captcha errado, digite: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cSeu captcha é válido!'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cUsuário VIP entrou no servidor cheio!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fDigite: /email add <e-mail> <e-mail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fDigite: /email change <e-mailAnterior> <novoE-mail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fDigite: /email recovery <e-mail>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] Novo e-mail inválido!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] E-mail anterior, inválido!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] E-mail iválido'
|
||||||
email_added: '[AuthMe] Email Added !'
|
email_added: '[AuthMe] E-mail adicionado com sucesso!'
|
||||||
email_confirm: '[AuthMe] Confirm your Email !'
|
email_confirm: '[AuthMe] Confirme seu e-mail!'
|
||||||
email_changed: '[AuthMe] Email Change !'
|
email_changed: '[AuthMe] E-mail alterado!'
|
||||||
email_send: '[AuthMe] Recovery Email Send !'
|
email_send: '[AuthMe] E-mail com nova senha enviado!'
|
||||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha CAPTCHA_TEXT'
|
|||||||
valid_captcha: '&cZadana captcha je OK !'
|
valid_captcha: '&cZadana captcha je OK !'
|
||||||
kick_forvip: '&cA VIP Hrac se pripojil na plny server!'
|
kick_forvip: '&cA VIP Hrac se pripojil na plny server!'
|
||||||
kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim !'
|
kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim !'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha <dasCaptcha>'
|
|||||||
valid_captcha: '&cDas Captcha ist korrekt!'
|
valid_captcha: '&cDas Captcha ist korrekt!'
|
||||||
kick_forvip: '&cEin VIP Spieler hat den vollen Server betreten!'
|
kick_forvip: '&cEin VIP Spieler hat den vollen Server betreten!'
|
||||||
kick_fullserver: '&cDer Server ist momentan voll, Sorry!'
|
kick_fullserver: '&cDer Server ist momentan voll, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cYour captcha is valid !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmeEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -42,8 +42,8 @@ wrong_captcha: '&cCaptcha incorrecto, please use : /captcha EL_CAPTCHA'
|
|||||||
valid_captcha: '&c¡ Captcha ingresado correctamente !'
|
valid_captcha: '&c¡ Captcha ingresado correctamente !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cVäärä varmistus, käytä : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cSinun varmistus epäonnistui.!'
|
valid_captcha: '&cSinun varmistus epäonnistui.!'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cYour captcha is valid !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
|
@ -41,13 +41,13 @@ wrong_captcha: '&cCaptcha sbagliato, perfavore fai: /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: "&cIl tuo captcha è valido!"
|
valid_captcha: "&cIl tuo captcha è valido!"
|
||||||
kick_forvip: "&cUn player VIP è entrato mentre il server era pieno!"
|
kick_forvip: "&cUn player VIP è entrato mentre il server era pieno!"
|
||||||
kick_fullserver: "&cIl server è attualmente pieno, ci dispiace!"
|
kick_fullserver: "&cIl server è attualmente pieno, ci dispiace!"
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUtilizzo: /email add <email> <confermaEmail>'
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUtilizzo: /email change <vecchiaEmail> <nuovaEmail>'
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUtilizzo: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] La nuova email non è valida!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] La vecchia email non è valida!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: "[AuthMe] L'email non è valida"
|
||||||
email_added: '[AuthMe] Email Added !'
|
email_added: '[AuthMe] Email Aggiunta!'
|
||||||
email_confirm: '[AuthMe] Confirm your Email !'
|
email_confirm: '[AuthMe] Conferma la tua Email!'
|
||||||
email_changed: '[AuthMe] Email Change !'
|
email_changed: '[AuthMe] Email cambiata!'
|
||||||
email_send: '[AuthMe] Recovery Email Send !'
|
email_send: '[AuthMe] Email di recupero inviata!'
|
||||||
|
@ -21,7 +21,7 @@ usage_unreg: '&c사용법: /unregister 비밀번호'
|
|||||||
pwd_changed: '&c비밀번호가 변경되었습니다!'
|
pwd_changed: '&c비밀번호가 변경되었습니다!'
|
||||||
user_unknown: '&c사용자 이름은 등록되지 않았습니다'
|
user_unknown: '&c사용자 이름은 등록되지 않았습니다'
|
||||||
password_error: 비밀번호가 일치하지 않습니다
|
password_error: 비밀번호가 일치하지 않습니다
|
||||||
unvalid_session: Session Dataes doesnt corrispond 세션이 끝날때 까지 기달려주세요
|
unvalid_session: 세션 데이터베이스가 일치하지 않습니다 세션이 끝날때 까지 기달려주세요
|
||||||
reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요
|
reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요
|
||||||
logged_in: '&c이미 로그인되어 있습니다!'
|
logged_in: '&c이미 로그인되어 있습니다!'
|
||||||
logout: '&c성공적으로 로그아웃되었습니다'
|
logout: '&c성공적으로 로그아웃되었습니다'
|
||||||
@ -41,13 +41,13 @@ wrong_captcha: '&c잘못된 캡차입니다, 올바른 사용법 : /captcha THE_
|
|||||||
valid_captcha: '&c당신의 캡차는 올바릅니다 !'
|
valid_captcha: '&c당신의 캡차는 올바릅니다 !'
|
||||||
kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!'
|
kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!'
|
||||||
kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!'
|
kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&f사용법: /email add <이메일> <이메일재입력> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&f사용법: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&f사용법: /email recovery <이메일>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] 새 이메일이 잘못되었습니다!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] 기존 이메일이 잘못되었습니다!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] 이메일이 잘못되었습니다'
|
||||||
email_added: '[AuthMe] Email Added !'
|
email_added: '[AuthMe] 이메일 추가됨 !'
|
||||||
email_confirm: '[AuthMe] Confirm your Email !'
|
email_confirm: '[AuthMe] 이메일을 확인해주세요 !'
|
||||||
email_changed: '[AuthMe] Email Change !'
|
email_changed: '[AuthMe] 이메일 변경됨 !'
|
||||||
email_send: '[AuthMe] Recovery Email Send !'
|
email_send: '[AuthMe] 복구 이메일 발송됨 !'
|
||||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&cNeteisinga Captcha, naudokite : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cJusu captcha Teisinga!'
|
valid_captcha: '&cJusu captcha Teisinga!'
|
||||||
kick_forvip: '&cA VIP prisijunge i pilna serveri!'
|
kick_forvip: '&cA VIP prisijunge i pilna serveri!'
|
||||||
kick_fullserver: '&cServeris yra pilnas, Atsiprasome.'
|
kick_fullserver: '&cServeris yra pilnas, Atsiprasome.'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cYour captcha is valid !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -15,7 +15,7 @@ max_reg: '&cAtingiu o numero máximo de registos permitidos'
|
|||||||
no_perm: '&cSem Permissões'
|
no_perm: '&cSem Permissões'
|
||||||
error: '&fOcorreu um erro; Por favor contacte um admin'
|
error: '&fOcorreu um erro; Por favor contacte um admin'
|
||||||
login_msg: '&cIdentifique-se com "/login password"'
|
login_msg: '&cIdentifique-se com "/login password"'
|
||||||
reg_msg: '&cPor favor registe-se com "/register password ConfirmePassword"'
|
reg_msg: '&cPor favor registe-se com "/register password confirmePassword"'
|
||||||
reg_email_msg: '&ePor favor registe-se com "/register <email> <confirmarEmail>"'
|
reg_email_msg: '&ePor favor registe-se com "/register <email> <confirmarEmail>"'
|
||||||
usage_unreg: '&cUse: /unregister password'
|
usage_unreg: '&cUse: /unregister password'
|
||||||
pwd_changed: '&cPassword alterada!'
|
pwd_changed: '&cPassword alterada!'
|
||||||
@ -41,10 +41,10 @@ wrong_captcha: '&cCaptcha errado, por favor use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cO seu captcha é válido!'
|
valid_captcha: '&cO seu captcha é válido!'
|
||||||
kick_forvip: '&cUm jogador VIP entrou no servidor cheio!'
|
kick_forvip: '&cUm jogador VIP entrou no servidor cheio!'
|
||||||
kick_fullserver: '&cO servidor está actualmente cheio, lamentamos!'
|
kick_fullserver: '&cO servidor está actualmente cheio, lamentamos!'
|
||||||
usage_email_add: '&fUse: /email add <Email> <confirmeEmail> '
|
usage_email_add: '&fUse: /email add <email> <confirmeEmail> '
|
||||||
usage_email_change: '&fUse: /email change <emailAntigo> <emailNovo> '
|
usage_email_change: '&fUse: /email change <emailAntigo> <emailNovo> '
|
||||||
usage_email_recovery: '&fUse: /email recovery <Email>'
|
usage_email_recovery: '&fUse: /email recovery <email>'
|
||||||
email_add: '/email add <Email> <confirmEmail>'
|
email_add: '/email add <email> <confirmeEmail>'
|
||||||
new_email_invalid: 'Novo email inválido!'
|
new_email_invalid: 'Novo email inválido!'
|
||||||
old_email_invalid: 'Email antigo inválido!'
|
old_email_invalid: 'Email antigo inválido!'
|
||||||
email_invalid: 'Email inválido!'
|
email_invalid: 'Email inválido!'
|
||||||
|
@ -46,9 +46,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cYour captcha is valid !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -10,7 +10,7 @@ usage_reg: '&cPríkaz: /register heslo zopakujHeslo'
|
|||||||
usage_log: '&cPríkaz: /login heslo'
|
usage_log: '&cPríkaz: /login heslo'
|
||||||
user_unknown: '&cZadané meno nie je zaregistrované!'
|
user_unknown: '&cZadané meno nie je zaregistrované!'
|
||||||
pwd_changed: '&cHeslo zmenené!'
|
pwd_changed: '&cHeslo zmenené!'
|
||||||
reg_only: '&fVstup iba pre registrovanych! Navstiv http://www.cs-gaming.eu pre registráciu'
|
reg_only: '&fVstup iba pre registrovanych! Navstiv http://example.com pre registráciu'
|
||||||
valid_session: '&cZapamätané prihlásenie'
|
valid_session: '&cZapamätané prihlásenie'
|
||||||
login_msg: '&cPrihlás sa príkazom "/login heslo"'
|
login_msg: '&cPrihlás sa príkazom "/login heslo"'
|
||||||
reg_msg: '&cZaregistruj sa príkazom "/register heslo zopakujHeslo"'
|
reg_msg: '&cZaregistruj sa príkazom "/register heslo zopakujHeslo"'
|
||||||
@ -45,9 +45,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA'
|
|||||||
valid_captcha: '&cYour captcha is valid !'
|
valid_captcha: '&cYour captcha is valid !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -41,9 +41,9 @@ wrong_captcha: '&c错误的验证码,请输入:“/captcha <验证码>”'
|
|||||||
valid_captcha: '&c你的验证码是有效的!'
|
valid_captcha: '&c你的验证码是有效的!'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -22,7 +22,7 @@ pwd_changed: '&c你成功的更換了你的密碼 !'
|
|||||||
user_unknown: '&c此用戶名沒有已登記資料 。'
|
user_unknown: '&c此用戶名沒有已登記資料 。'
|
||||||
password_error: '&f密碼不符合 。'
|
password_error: '&f密碼不符合 。'
|
||||||
unvalid_session: '&f登入階段資料已損壞 , 請等待登入階段結束 。'
|
unvalid_session: '&f登入階段資料已損壞 , 請等待登入階段結束 。'
|
||||||
reg_only: '&f限已註冊會員 , 請先到 http://member.usociety.org 註冊 。'
|
reg_only: '&f限已註冊會員 , 請先到 http://example.com 註冊 。'
|
||||||
logged_in: '&c你已經登入過了 。'
|
logged_in: '&c你已經登入過了 。'
|
||||||
logout: '&b你成功的登出了 。'
|
logout: '&b你成功的登出了 。'
|
||||||
same_nick: '&f同名玩家已在遊玩 。'
|
same_nick: '&f同名玩家已在遊玩 。'
|
||||||
@ -41,9 +41,9 @@ wrong_captcha: '&c你輸入了錯誤的驗證碼,請使用 《 /captcha <驗
|
|||||||
valid_captcha: '&c你的驗證碼是無效的 !'
|
valid_captcha: '&c你的驗證碼是無效的 !'
|
||||||
kick_forvip: '&cA VIP Player join the full server!'
|
kick_forvip: '&cA VIP Player join the full server!'
|
||||||
kick_fullserver: '&cThe server is actually full, Sorry!'
|
kick_fullserver: '&cThe server is actually full, Sorry!'
|
||||||
usage_email_add: '&fUsage: /email add <Email> <ConfirmeEmail> '
|
usage_email_add: '&fUsage: /email add <email> <confirmEmail> '
|
||||||
usage_email_change: '&fUsage: /email change <EmailAntigo> <NovoEmail> '
|
usage_email_change: '&fUsage: /email change <oldEmail> <newEmail> '
|
||||||
usage_email_recovery: '&fUsage: /email recovery <Email>'
|
usage_email_recovery: '&fUsage: /email recovery <email>'
|
||||||
new_email_invalid: '[AuthMe] New email invalid!'
|
new_email_invalid: '[AuthMe] New email invalid!'
|
||||||
old_email_invalid: '[AuthMe] Old email invalid!'
|
old_email_invalid: '[AuthMe] Old email invalid!'
|
||||||
email_invalid: '[AuthMe] Invalid Email'
|
email_invalid: '[AuthMe] Invalid Email'
|
||||||
|
@ -3,7 +3,7 @@ author: Xephi59
|
|||||||
website: http://www.multiplayer-italia.com/
|
website: http://www.multiplayer-italia.com/
|
||||||
description: AuthMe prevents people, which aren't logged in, from doing stuff like placing blocks, moving, typing commands or seeing the inventory of the current player.
|
description: AuthMe prevents people, which aren't logged in, from doing stuff like placing blocks, moving, typing commands or seeing the inventory of the current player.
|
||||||
main: uk.org.whoami.authme.AuthMe
|
main: uk.org.whoami.authme.AuthMe
|
||||||
version: 2.9.2
|
version: 2.9.3
|
||||||
softdepend: [Vault, ChestShop, Spout, Multiverse-Core, Notifications, Citizens, CombatTag, Essentials, EssentialsSpawn]
|
softdepend: [Vault, ChestShop, Spout, Multiverse-Core, Notifications, Citizens, CombatTag, Essentials, EssentialsSpawn]
|
||||||
commands:
|
commands:
|
||||||
register:
|
register:
|
||||||
|
Loading…
Reference in New Issue
Block a user