Now compatible with AuthMe databases!
This commit is contained in:
parent
17e612a708
commit
ab5b8f6cb5
|
@ -275,7 +275,7 @@ public class YamlConfig implements ConfigurationAdapter {
|
||||||
@Override
|
@Override
|
||||||
public AuthServiceInfo getAuthSettings() {
|
public AuthServiceInfo getAuthSettings() {
|
||||||
final Map<String, Object> auth = this.get("authservice", new HashMap<String, Object>());
|
final Map<String, Object> auth = this.get("authservice", new HashMap<String, Object>());
|
||||||
return new AuthServiceInfo(this.get("enabled", false, auth), this.get("authfile", "auth.uwu", auth), this.get("ip_limit", 0, auth));
|
return new AuthServiceInfo(this.get("enabled", false, auth), this.get("authfile", "auths.db", auth), this.get("ip_limit", 0, auth));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class AuthHandler extends PacketHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnected(final ChannelWrapper channel) throws Exception {
|
public void disconnected(final ChannelWrapper channel) {
|
||||||
this.loggedIn = true;
|
this.loggedIn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ public class AuthHandler extends PacketHandler {
|
||||||
} else if (!authSystem.isRegistered(this.username)) {
|
} else if (!authSystem.isRegistered(this.username)) {
|
||||||
this.con.sendMessage("\u00A7cThis username is not registered on this server!");
|
this.con.sendMessage("\u00A7cThis username is not registered on this server!");
|
||||||
} else if (authSystem.login(this.username, args[1])) {
|
} else if (authSystem.login(this.username, args[1])) {
|
||||||
|
this.con.sendMessage("\u00A7cLogging in...");
|
||||||
this.onLogin();
|
this.onLogin();
|
||||||
} else {
|
} else {
|
||||||
this.con.sendMessage("\u00A7cThat password is invalid!");
|
this.con.sendMessage("\u00A7cThat password is invalid!");
|
||||||
|
@ -101,7 +102,8 @@ public class AuthHandler extends PacketHandler {
|
||||||
this.con.sendMessage("\u00A7cThose passwords do not match!");
|
this.con.sendMessage("\u00A7cThose passwords do not match!");
|
||||||
} else if (authSystem.isRegistered(this.username)) {
|
} else if (authSystem.isRegistered(this.username)) {
|
||||||
this.con.sendMessage("\u00A7cThis username is already registered!");
|
this.con.sendMessage("\u00A7cThis username is already registered!");
|
||||||
} else if (authSystem.register(this.username, args[1], this.con.getAddress().toString())) {
|
} else if (authSystem.register(this.username, args[1], this.con.getAddress().getAddress().getHostAddress())) {
|
||||||
|
this.con.sendMessage("\u00A7cSuccessfully registered and logging in...");
|
||||||
this.onLogin();
|
this.onLogin();
|
||||||
} else {
|
} else {
|
||||||
this.con.sendMessage("\u00A7cUnable to register...");
|
this.con.sendMessage("\u00A7cUnable to register...");
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
package net.md_5.bungee.eaglercraft;
|
package net.md_5.bungee.eaglercraft;
|
||||||
|
|
||||||
import com.google.common.hash.Hashing;
|
import net.md_5.bungee.BungeeCord;
|
||||||
import net.md_5.bungee.api.config.AuthServiceInfo;
|
import net.md_5.bungee.api.config.AuthServiceInfo;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class AuthSystem {
|
public class AuthSystem {
|
||||||
private final String authFileName;
|
private final String authFileName;
|
||||||
|
@ -25,12 +26,16 @@ public class AuthSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AuthData {
|
private static class AuthData {
|
||||||
public String passHash;
|
public String salt;
|
||||||
public Set<String> ips;
|
public String hash;
|
||||||
|
public String ip;
|
||||||
|
public long timestamp;
|
||||||
|
|
||||||
public AuthData(String p, Set<String> i) {
|
public AuthData(String salt, String hash, String ip, long timestamp) {
|
||||||
passHash = p;
|
this.salt = salt;
|
||||||
ips = i;
|
this.hash = hash;
|
||||||
|
this.ip = ip;
|
||||||
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +46,9 @@ public class AuthSystem {
|
||||||
AuthData authData = database.get(username);
|
AuthData authData = database.get(username);
|
||||||
if (authData != null) return false;
|
if (authData != null) return false;
|
||||||
if (isIpAtTheLimit(ip)) return false;
|
if (isIpAtTheLimit(ip)) return false;
|
||||||
String hash = Hashing.sha256().hashString(password).toString();
|
String salt = createSalt(16);
|
||||||
Set<String> initIps = new HashSet<>();
|
String hash = getSaltedHash(password, salt);
|
||||||
initIps.add(ip);
|
database.put(username, new AuthData(salt, hash, ip, System.currentTimeMillis()));
|
||||||
database.put(username, new AuthData(hash, initIps));
|
|
||||||
writeDatabase();
|
writeDatabase();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +63,8 @@ public class AuthSystem {
|
||||||
public boolean changePass(String username, String password) {
|
public boolean changePass(String username, String password) {
|
||||||
synchronized (database) {
|
synchronized (database) {
|
||||||
AuthData authData = database.get(username);
|
AuthData authData = database.get(username);
|
||||||
authData.passHash = Hashing.sha256().hashString(password).toString();
|
authData.salt = createSalt(16);
|
||||||
|
authData.hash = getSaltedHash(password, authData.salt);
|
||||||
writeDatabase();
|
writeDatabase();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +74,7 @@ public class AuthSystem {
|
||||||
synchronized (database) {
|
synchronized (database) {
|
||||||
AuthData authData = database.get(username);
|
AuthData authData = database.get(username);
|
||||||
if (authData == null) return false;
|
if (authData == null) return false;
|
||||||
return authData.passHash.equals(Hashing.sha256().hashString(password).toString());
|
return authData.hash.equals(getSaltedHash(password, authData.salt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +83,7 @@ public class AuthSystem {
|
||||||
if (this.ipLimit <= 0) return false;
|
if (this.ipLimit <= 0) return false;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
for (AuthData authData : database.values()) {
|
for (AuthData authData : database.values()) {
|
||||||
if (authData.ips.contains(ip)) num++;
|
if (authData.ip.equals(ip)) num++;
|
||||||
if (num >= this.ipLimit) {
|
if (num >= this.ipLimit) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -94,18 +99,24 @@ public class AuthSystem {
|
||||||
File authFile = new File(this.authFileName);
|
File authFile = new File(this.authFileName);
|
||||||
if (!authFile.exists()) authFile.createNewFile();
|
if (!authFile.exists()) authFile.createNewFile();
|
||||||
|
|
||||||
Map<String, AuthData> cache = new HashMap<>();
|
database.clear();
|
||||||
|
|
||||||
String[] lines = new String(Files.readAllBytes(authFile.toPath())).trim().split("\n");
|
String[] lines = new String(Files.readAllBytes(authFile.toPath())).trim().split("\n");
|
||||||
if (lines.length == 1 && lines[0].isEmpty()) return;
|
if (lines.length == 1 && lines[0].isEmpty()) return;
|
||||||
|
boolean alreadyLogged = false;
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
String[] pieces = line.split("\u0000");
|
String[] pieces = line.split(":");
|
||||||
cache.put(pieces[0], new AuthData(pieces[2], new HashSet<>(Arrays.asList(pieces[1].split("\u00A7")))));
|
if (!pieces[1].startsWith("$SHA$")) {
|
||||||
|
if (!alreadyLogged) {
|
||||||
|
alreadyLogged = true;
|
||||||
|
BungeeCord.getInstance().getLogger().warning("One or more entries in the auth file are hashed in an unsupported format! (not SHA-256!)");
|
||||||
|
}
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
String[] saltHash = pieces[1].substring(pieces[1].substring(1).indexOf('$') + 2).split("\\$");
|
||||||
|
database.put(pieces[0], new AuthData(saltHash[0], saltHash[1], pieces[2], Long.parseLong(pieces[3])));
|
||||||
}
|
}
|
||||||
|
|
||||||
database.clear();
|
|
||||||
database.putAll(cache);
|
|
||||||
cache.clear();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -119,10 +130,14 @@ public class AuthSystem {
|
||||||
for (String username : database.keySet()) {
|
for (String username : database.keySet()) {
|
||||||
AuthData entry = database.get(username);
|
AuthData entry = database.get(username);
|
||||||
out.append(username);
|
out.append(username);
|
||||||
out.append("\u0000");
|
out.append(":$SHA$");
|
||||||
out.append(String.join("\u00A7", entry.ips));
|
out.append(entry.salt);
|
||||||
out.append("\u0000");
|
out.append("$");
|
||||||
out.append(entry.passHash);
|
out.append(entry.hash);
|
||||||
|
out.append(":");
|
||||||
|
out.append(entry.ip);
|
||||||
|
out.append(":");
|
||||||
|
out.append(entry.timestamp);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,4 +148,37 @@ public class AuthSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hashing used is based on hashing from AuthMe
|
||||||
|
|
||||||
|
private static final SecureRandom rnd = new SecureRandom();
|
||||||
|
|
||||||
|
private static String getSHA256(String message) {
|
||||||
|
try {
|
||||||
|
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
||||||
|
sha256.reset();
|
||||||
|
sha256.update(message.getBytes());
|
||||||
|
byte[] digest = sha256.digest();
|
||||||
|
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSaltedHash(String message, String salt) {
|
||||||
|
return getSHA256(getSHA256(message) + salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createSalt(int length) {
|
||||||
|
try {
|
||||||
|
byte[] msg = new byte[40];
|
||||||
|
rnd.nextBytes(msg);
|
||||||
|
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
|
||||||
|
sha1.reset();
|
||||||
|
byte[] digest = sha1.digest(msg);
|
||||||
|
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest)).substring(0, length);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user