Now compatible with AuthMe databases!

This commit is contained in:
ayunami2000 2022-07-24 12:53:57 -04:00
parent 17e612a708
commit ab5b8f6cb5
3 changed files with 79 additions and 29 deletions

View File

@ -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

View File

@ -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...");

View File

@ -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 "";
}
}
} }