diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java index 4623187..d4fa3e3 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java @@ -62,6 +62,7 @@ import net.md_5.bungee.api.scheduler.TaskScheduler; import net.md_5.bungee.api.tab.CustomTabList; import net.md_5.bungee.command.CommandAlert; import net.md_5.bungee.command.CommandBungee; +import net.md_5.bungee.command.CommandChangePassword; import net.md_5.bungee.command.CommandClearRatelimit; import net.md_5.bungee.command.CommandConfirmCode; import net.md_5.bungee.command.CommandDomain; @@ -87,6 +88,7 @@ import net.md_5.bungee.command.CommandServer; import net.md_5.bungee.command.ConsoleCommandSender; import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.YamlConfig; +import net.md_5.bungee.eaglercraft.AuthSystem; import net.md_5.bungee.eaglercraft.BanList; import net.md_5.bungee.eaglercraft.DomainBlacklist; import net.md_5.bungee.eaglercraft.PluginEaglerSkins; @@ -126,6 +128,7 @@ public class BungeeCord extends ProxyServer { private ConsoleReader consoleReader; private final Logger logger; private Collection banCommands; + public AuthSystem authSystem; public static BungeeCord getInstance() { return (BungeeCord) ProxyServer.getInstance(); @@ -234,7 +237,10 @@ public class BungeeCord extends ProxyServer { this.pluginManager.detectPlugins(this.pluginsFolder); this.pluginManager.addInternalPlugin(new PluginEaglerSkins()); this.pluginManager.addInternalPlugin(new PluginEaglerVoice(this.config.getVoiceEnabled())); - //if(this.config.getAuthInfo().isEnabled()) this.pluginManager.addInternalPlugin(new PluginEaglerAuth()); + if (this.config.getAuthInfo().isEnabled()) { + this.authSystem = new AuthSystem(this.config.getAuthInfo()); + this.getPluginManager().registerCommand(null, new CommandChangePassword(this.authSystem)); + } if (this.reconnectHandler == null) { this.reconnectHandler = new SQLReconnectHandler(); } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java index 95f2089..b8ac4ef 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java @@ -28,7 +28,7 @@ public class ServerConnection implements Server { @Override public synchronized void disconnect(final String reason) { - if (!this.ch.isClosed()) { + if (this.ch != null && !this.ch.isClosed()) { this.unsafe().sendPacket(new PacketFFKick(reason)); this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() { @Override @@ -41,7 +41,7 @@ public class ServerConnection implements Server { @Override public InetSocketAddress getAddress() { - return this.getInfo().getAddress(); + return this.getInfo() == null ? null : this.getInfo().getAddress(); } @Override @@ -54,7 +54,7 @@ public class ServerConnection implements Server { this.unsafe = new Connection.Unsafe() { @Override public void sendPacket(final DefinedPacket packet) { - ServerConnection.this.ch.write(packet); + if (ServerConnection.this.ch != null) ServerConnection.this.ch.write(packet); } }; this.ch = ch; diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java index fd52e63..454026b 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java @@ -1,35 +1,35 @@ package net.md_5.bungee.api.config; -import java.io.File; +import java.util.List; public class AuthServiceInfo { private final boolean enabled; - private final String limbo; - private final File authfile; - private final int timeout; + private final String authfile; + private final int ipLimit; + private final List joinMessages; - public AuthServiceInfo(boolean enabled, String limbo, File authfile, int timeout) { + public AuthServiceInfo(boolean enabled, String authfile, int timeout, List joinMessages) { this.enabled = enabled; - this.limbo = limbo; this.authfile = authfile; - this.timeout = timeout; + this.ipLimit = timeout; + this.joinMessages = joinMessages; } public boolean isEnabled() { return enabled; } - public String getLimbo() { - return limbo; - } - - public File getAuthfile() { + public String getAuthfile() { return authfile; } - public int getTimeout() { - return timeout; + public int getIpLimit() { + return ipLimit; + } + + public List getJoinMessages() { + return joinMessages; } } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandChangePassword.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandChangePassword.java new file mode 100644 index 0000000..aad99cb --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandChangePassword.java @@ -0,0 +1,34 @@ +package net.md_5.bungee.command; + +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.eaglercraft.AuthSystem; + +public class CommandChangePassword extends Command { + private final AuthSystem authSystem; + + public CommandChangePassword(AuthSystem authSystem) { + super("changepassword", "bungeecord.command.eag.changepassword", new String[] { "changepwd", "changepasswd", "changepass" }); + this.authSystem = authSystem; + } + + @Override + public void execute(final CommandSender sender, final String[] args) { + if (!(sender instanceof ProxiedPlayer)) { + return; + } + String username = sender.getName(); + if (args.length == 0 || args.length == 1) { + sender.sendMessage("\u00A7cUsage: /changepassword "); + } else if (this.authSystem.login(username, args[0])) { + if (this.authSystem.changePass(username, args[1])) { + sender.sendMessage("\u00A7cPassword changed successfully!"); + } else { + sender.sendMessage("\u00A7cUnable to change your password..."); + } + } else { + sender.sendMessage("\u00A7cThe old password specified is incorrect!"); + } + } +} \ No newline at end of file diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java index 9005d80..34b0354 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; @@ -69,13 +70,15 @@ public class YamlConfig implements ConfigurationAdapter { } catch (IOException ex) { throw new RuntimeException("Could not load configuration!", ex); } - final Map permissions = this.get("permissions", new HashMap()); + final Map> permissions = this.get("permissions", new HashMap>()); if (permissions.isEmpty()) { - permissions.put("default", Arrays.asList("bungeecord.command.server", "bungeecord.command.list", "bungeecord.command.eag.domain")); + permissions.put("default", Arrays.asList("bungeecord.command.server", "bungeecord.command.list", "bungeecord.command.eag.domain", "bungeecord.command.eag.changepassword")); permissions.put("admin", Arrays.asList("bungeecord.command.alert", "bungeecord.command.end", "bungeecord.command.ip", "bungeecord.command.reload", "bungeecord.command.eag.ban", "bungeecord.command.eag.banwildcard", "bungeecord.command.eag.banip", "bungeecord.command.eag.banregex", "bungeecord.command.eag.reloadban", "bungeecord.command.eag.banned", "bungeecord.command.eag.banlist", "bungeecord.command.eag.unban", "bungeecord.command.eag.ratelimit", "bungeecord.command.eag.blockdomain", "bungeecord.command.eag.blockdomainname", "bungeecord.command.eag.unblockdomain")); + } else if (this.get("authservice", new HashMap()).isEmpty() && permissions.containsKey("default") && !permissions.get("default").contains("bungeecord.command.eag.changepassword")) { + permissions.get("default").add("bungeecord.command.eag.changepassword"); } this.get("groups", new HashMap()); } @@ -275,9 +278,10 @@ public class YamlConfig implements ConfigurationAdapter { @Override public AuthServiceInfo getAuthSettings() { - //final Map auth = this.get("authservice", new HashMap()); - //return new AuthServiceInfo(this.get("enabled", true, auth), this.get("limbo", "lobby", auth), new File(this.get("authfile", "passwords.yml", auth)), this.get("timeout", 30, auth)); - return null; + final Map auth = this.get("authservice", new HashMap()); + final List defaultJoinMessages = new ArrayList(); + defaultJoinMessages.add("&3Welcome to my &aEaglercraftBungee &3server!"); + return new AuthServiceInfo(this.get("enabled", false, auth), this.get("authfile", "auths.db", auth), this.get("ip_limit", 0, auth), this.get("join_messages", defaultJoinMessages, auth)); } @Override diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 9786915..e09318a 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -35,6 +35,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.PostLoginEvent; import net.md_5.bungee.api.event.ProxyPingEvent; +import net.md_5.bungee.eaglercraft.AuthHandler; import net.md_5.bungee.eaglercraft.BanList; import net.md_5.bungee.eaglercraft.BanList.BanCheck; import net.md_5.bungee.eaglercraft.BanList.BanState; @@ -47,15 +48,7 @@ import net.md_5.bungee.netty.PacketDecoder; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.Forge; -import net.md_5.bungee.protocol.packet.DefinedPacket; -import net.md_5.bungee.protocol.packet.Packet1Login; -import net.md_5.bungee.protocol.packet.Packet2Handshake; -import net.md_5.bungee.protocol.packet.PacketCDClientStatus; -import net.md_5.bungee.protocol.packet.PacketFAPluginMessage; -import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse; -import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest; -import net.md_5.bungee.protocol.packet.PacketFEPing; -import net.md_5.bungee.protocol.packet.PacketFFKick; +import net.md_5.bungee.protocol.packet.*; public class InitialHandler extends PacketHandler implements PendingConnection { private final ProxyServer bungee; @@ -259,10 +252,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection { userCon.getAttachment().put("origin", origin); } userCon.init(); - this.bungee.getPluginManager().callEvent(new PostLoginEvent(userCon)); - ((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class)).setHandler(new UpstreamBridge(this.bungee, userCon)); - final ServerInfo server = this.bungee.getReconnectHandler().getServer(userCon); - userCon.connect(server, true); + HandlerBoss handlerBoss = ((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class)); + if (BungeeCord.getInstance().config.getAuthInfo().isEnabled()) { + handlerBoss.setHandler(new AuthHandler(this.bungee, userCon, handlerBoss)); + } else { + this.bungee.getPluginManager().callEvent(new PostLoginEvent(userCon)); + handlerBoss.setHandler(new UpstreamBridge(this.bungee, userCon)); + final ServerInfo server = this.bungee.getReconnectHandler().getServer(userCon); + userCon.connect(server, true); + } this.thisState = State.FINISHED; throw new CancelSendSignal(); } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 6e550f0..59d5a76 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -55,7 +55,7 @@ public class UpstreamBridge extends PacketHandler { @Override public void handle(final byte[] buf) throws Exception { EntityMap.rewrite(buf, this.con.getClientEntityId(), this.con.getServerEntityId()); - if (this.con.getServer() != null) { + if (this.con.getServer() != null && this.con.getServer().getCh() != null) { this.con.getServer().getCh().write(buf); } } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthHandler.java new file mode 100644 index 0000000..65b2dfc --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthHandler.java @@ -0,0 +1,153 @@ +package net.md_5.bungee.eaglercraft; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.ServerConnection; +import net.md_5.bungee.UserConnection; +import net.md_5.bungee.Util; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.event.PostLoginEvent; +import net.md_5.bungee.connection.UpstreamBridge; +import net.md_5.bungee.netty.ChannelWrapper; +import net.md_5.bungee.netty.HandlerBoss; +import net.md_5.bungee.netty.PacketHandler; +import net.md_5.bungee.protocol.packet.Packet1Login; +import net.md_5.bungee.protocol.packet.Packet9Respawn; +import net.md_5.bungee.protocol.packet.Packet0DPositionAndLook; +import net.md_5.bungee.protocol.packet.Packet3Chat; +import net.md_5.bungee.protocol.packet.Packet0KeepAlive; +import net.md_5.bungee.protocol.packet.PacketCCSettings; + +public class AuthHandler extends PacketHandler { + private static final AuthSystem authSystem = BungeeCord.getInstance().authSystem; + + private final ProxyServer bungee; + private final UserConnection con; + private final HandlerBoss handlerBoss; + private final String username; + + private boolean loggedIn = false; + + public AuthHandler(final ProxyServer bungee, final UserConnection con, final HandlerBoss handlerBoss) { + this.bungee = bungee; + this.con = con; + this.handlerBoss = handlerBoss; + + this.username = this.con.getName(); + + new Thread(() -> { + for (int i = 0; i < 120; i++) { + if (this.loggedIn) break; + try { + Thread.sleep(250); + } catch (InterruptedException ignored) { } + } + if (this.loggedIn) return; + this.con.disconnect("You did not login in time!"); + }).start(); + + this.con.unsafe().sendPacket(new Packet1Login(0, "END", (byte) 2, 1, (byte) 0, (byte) 0, (byte) this.con.getPendingConnection().getListener().getTabListSize())); + this.con.unsafe().sendPacket(new Packet9Respawn(1, (byte) 0, (byte) 2, (short) 255, "END")); + this.con.unsafe().sendPacket(new Packet0DPositionAndLook(0, 0, 0, 0, 0f, 0f, true)); + + this.con.sendMessages(authSystem.joinMessages); + + if (authSystem.isRegistered(this.username)) { + this.con.sendMessage("\u00A7cPlease login to continue! /login "); + } else { + this.con.sendMessage("\u00A7cPlease register to continue! /register "); + } + } + + @Override + public void exception(final Throwable t) throws Exception { + this.con.disconnect(Util.exception(t)); + } + + @Override + public void disconnected(final ChannelWrapper channel) { + this.loggedIn = true; + } + + @Override + public void handle(final Packet0KeepAlive alive) throws Exception { + if (alive.getRandomId() == this.con.getSentPingId()) { + final int newPing = (int) (System.currentTimeMillis() - this.con.getSentPingTime()); + this.con.setPing(newPing); + } + } + + @Override + public void handle(final Packet3Chat chat) throws Exception { + String message = chat.getMessage(); + if (message.startsWith("/")) { + String[] args = message.substring(1).trim().split(" "); + switch (args[0]) { + case "login": + case "l": + if (args.length == 1) { + this.con.sendMessage("\u00A7cYou must specify a password to login! /login "); + } else if (!authSystem.isRegistered(this.username)) { + this.con.sendMessage("\u00A7cThis username is not registered on this server!"); + } else if (authSystem.login(this.username, args[1])) { + this.con.sendMessage("\u00A7cLogging in..."); + this.onLogin(); + } else { + this.con.sendMessage("\u00A7cThat password is invalid!"); + } + break; + case "register": + case "reg": + if (args.length == 1 || args.length == 2) { + this.con.sendMessage("\u00A7cUsage: /" + args[0].toLowerCase() + " "); + } else if (!args[1].equals(args[2])) { + this.con.sendMessage("\u00A7cThose passwords do not match!"); + } else if (authSystem.isRegistered(this.username)) { + this.con.sendMessage("\u00A7cThis username is already registered!"); + } else if (authSystem.register(this.username, args[1], this.con.getAddress().getAddress().getHostAddress())) { + this.con.sendMessage("\u00A7cSuccessfully registered and logging in..."); + this.onLogin(); + } else { + this.con.sendMessage("\u00A7cUnable to register..."); + } + break; + case "changepassword": + case "changepasswd": + case "changepwd": + case "changepass": + if (args.length == 1 || args.length == 2) { + this.con.sendMessage("\u00A7cUsage: /" + args[0].toLowerCase() + " "); + } else if (authSystem.login(this.username, args[1])) { + if (authSystem.changePass(this.username, args[2])) { + this.con.sendMessage("\u00A7cPassword changed successfully!"); + } else { + this.con.sendMessage("\u00A7cUnable to change your password..."); + } + } else { + this.con.sendMessage("\u00A7cThe old password specified is incorrect!"); + } + break; + default: + } + } + } + + private void onLogin() { + this.loggedIn = true; + this.bungee.getPluginManager().callEvent(new PostLoginEvent(this.con)); + handlerBoss.setHandler(new UpstreamBridge(this.bungee, this.con)); + final ServerInfo server = this.bungee.getReconnectHandler().getServer(this.con); + this.con.setServer(new ServerConnection(null, null)); + this.con.connect(server, true); + } + + @Override + public void handle(final PacketCCSettings settings) throws Exception { + this.con.setSettings(settings); + } + + @Override + public String toString() { + return "[" + this.con.getName() + "] -> AuthHandler"; + } +} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthSystem.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthSystem.java new file mode 100644 index 0000000..1c8f40d --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/AuthSystem.java @@ -0,0 +1,193 @@ +package net.md_5.bungee.eaglercraft; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.config.AuthServiceInfo; + +import java.io.File; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AuthSystem { + private final String authFileName; + private final int ipLimit; + public final String[] joinMessages; + + public AuthSystem(AuthServiceInfo authInfo) { + this.authFileName = authInfo.getAuthfile(); + this.ipLimit = authInfo.getIpLimit(); + List listJoinMessages = authInfo.getJoinMessages(); + String[] arrayJoinMessages = new String[listJoinMessages.size()]; + for (int i = 0; i < listJoinMessages.size(); i++) { + arrayJoinMessages[i] = ChatColor.translateAlternateColorCodes('&', listJoinMessages.get(i)); + } + this.joinMessages = arrayJoinMessages; + + this.readDatabase(); + } + + private static class AuthData { + public String salt; + public String hash; + public String ip; + public long timestamp; + + public AuthData(String salt, String hash, String ip, long timestamp) { + this.salt = salt; + this.hash = hash; + this.ip = ip; + this.timestamp = timestamp; + } + } + + private final Map database = new HashMap<>(); + + public boolean register(String username, String password, String ip) { + synchronized (database) { + AuthData authData = database.get(username); + if (authData != null) return false; + if (isIpAtTheLimit(ip)) return false; + String salt = createSalt(16); + String hash = getSaltedHash(password, salt); + database.put(username, new AuthData(salt, hash, ip, System.currentTimeMillis())); + writeDatabase(); + return true; + } + } + + public boolean isRegistered(String username) { + synchronized (database) { + return database.containsKey(username); + } + } + + public boolean changePass(String username, String password) { + synchronized (database) { + AuthData authData = database.get(username); + authData.salt = createSalt(16); + authData.hash = getSaltedHash(password, authData.salt); + writeDatabase(); + return true; + } + } + + public boolean login(String username, String password) { + synchronized (database) { + AuthData authData = database.get(username); + if (authData == null) return false; + return authData.hash.equals(getSaltedHash(password, authData.salt)); + } + } + + private boolean isIpAtTheLimit(String ip) { + synchronized (database) { + if (this.ipLimit <= 0) return false; + int num = 0; + for (AuthData authData : database.values()) { + if (authData.ip.equals(ip)) num++; + if (num >= this.ipLimit) { + return true; + } + } + return false; + } + } + + // only use once, on load + public void readDatabase() { + synchronized (database) { + try { + File authFile = new File(this.authFileName); + if (!authFile.exists()) authFile.createNewFile(); + + database.clear(); + + String[] lines = new String(Files.readAllBytes(authFile.toPath())).trim().split("\n"); + if (lines.length == 1 && lines[0].isEmpty()) return; + boolean alreadyLogged = false; + for (String line : lines) { + String[] pieces = line.split(":"); + 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]))); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private void writeDatabase() { + synchronized (database) { + StringBuilder out = new StringBuilder(); + + for (String username : database.keySet()) { + AuthData entry = database.get(username); + out.append(username); + out.append(":$SHA$"); + out.append(entry.salt); + out.append("$"); + out.append(entry.hash); + out.append(":"); + out.append(entry.ip); + out.append(":"); + out.append(entry.timestamp); + out.append("\n"); + } + + try { + Files.write(Paths.get(this.authFileName), out.toString().getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + // 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 ""; + } + } +} \ No newline at end of file diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java deleted file mode 100644 index 14bd16a..0000000 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.md_5.bungee.eaglercraft; - -import java.util.Collections; -import java.util.HashSet; - -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.api.event.ServerConnectEvent; -import net.md_5.bungee.api.plugin.Listener; -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.api.plugin.PluginDescription; -import net.md_5.bungee.event.EventHandler; - -public class PluginEaglerAuth extends Plugin implements Listener { - - public PluginEaglerAuth() { - super(new PluginDescription("EaglerAuth", PluginEaglerAuth.class.getName(), "1.0.0", "LAX1DUDE", Collections.emptySet(), null)); - } - - @Override - public void onLoad() { - - } - - @Override - public void onEnable() { - getProxy().getPluginManager().registerListener(this, this); - } - - @Override - public void onDisable() { - - } - - private final HashSet playersInLimbo = new HashSet(); - - @EventHandler - public void onPostLogin(PostLoginEvent event) { - //playersInLimbo.add(event.getPlayer()); - } - - @EventHandler - public void onServerConnect(ServerConnectEvent event) { - ProxiedPlayer player = event.getPlayer(); - //if(playersInLimbo.contains(player)) { - // event.setCancelled(true); - // player.unsafe().sendPacket(new Packet1Login(0, "END", (byte) 1, 1, (byte) 0, (byte) 0, (byte) 1)); - // player.unsafe().sendPacket(new Packet9Respawn(1, (byte) 0, (byte) 1, (short) 255, "END")); - //} - } - -} diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java index 855560a..83ad08e 100644 --- a/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java @@ -55,4 +55,7 @@ public abstract class AbstractPacketHandler { public void handle(final PacketFFKick kick) throws Exception { } + + public void handle(final Packet0DPositionAndLook positionAndLook) throws Exception { + } } diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/Packet0DPositionAndLook.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/Packet0DPositionAndLook.java new file mode 100644 index 0000000..0911cd2 --- /dev/null +++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/protocol/packet/Packet0DPositionAndLook.java @@ -0,0 +1,114 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; + +public class Packet0DPositionAndLook extends DefinedPacket { + private double x; + private double y; + private double stance; + private double z; + private float yaw; + private float pitch; + private boolean onGround; + + private Packet0DPositionAndLook() { + super(13); + } + + public Packet0DPositionAndLook(final int x, final int y, final double stance, final double z, final float yaw, final float pitch, final boolean onGround) { + this(); + this.x = x; + this.y = y; + this.stance = stance; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + this.onGround = onGround; + } + + @Override + public void read(final ByteBuf buf) { + this.x = buf.readDouble(); + this.y = buf.readDouble(); + this.stance = buf.readDouble(); + this.z = buf.readDouble(); + this.yaw = buf.readFloat(); + this.pitch = buf.readFloat(); + this.onGround = buf.readBoolean(); + } + + @Override + public void write(final ByteBuf buf) { + buf.writeDouble(this.x); + buf.writeDouble(this.y); + buf.writeDouble(this.stance); + buf.writeDouble(this.z); + buf.writeFloat(this.yaw); + buf.writeFloat(this.pitch); + buf.writeBoolean(this.onGround); + } + + @Override + public void handle(final AbstractPacketHandler handler) throws Exception { + handler.handle(this); + } + + @Override + public String toString() { + return "Packet0DPositionAndLook(tooLazyToFillThisInLOL)"; + } + + @Override + public boolean equals(final Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Packet0DPositionAndLook)) { + return false; + } + final Packet0DPositionAndLook other = (Packet0DPositionAndLook) o; + if (!other.canEqual(this)) { + return false; + } + if (this.x != other.x) { + return false; + } + if (this.y != other.y) { + return false; + } + if (this.stance != other.stance) { + return false; + } + if (this.z != other.z) { + return false; + } + if (this.yaw != other.yaw) { + return false; + } + if (this.pitch != other.pitch) { + return false; + } + if (this.onGround != other.onGround) { + return false; + } + return false; + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = result * 31 + Double.hashCode(this.x); + result = result * 31 + Double.hashCode(this.y); + result = result * 31 + Double.hashCode(this.stance); + result = result * 31 + Double.hashCode(this.z); + result = result * 31 + Float.hashCode(this.yaw); + result = result * 31 + Float.hashCode(this.pitch); + result = result * 31 + Boolean.hashCode(this.onGround); + return result; + } + + public boolean canEqual(final Object other) { + return other instanceof Packet0DPositionAndLook; + } +}