Merge remote-tracking branch 'origin/auth'
This commit is contained in:
commit
c4bda6bec5
|
@ -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.api.tab.CustomTabList;
|
||||||
import net.md_5.bungee.command.CommandAlert;
|
import net.md_5.bungee.command.CommandAlert;
|
||||||
import net.md_5.bungee.command.CommandBungee;
|
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.CommandClearRatelimit;
|
||||||
import net.md_5.bungee.command.CommandConfirmCode;
|
import net.md_5.bungee.command.CommandConfirmCode;
|
||||||
import net.md_5.bungee.command.CommandDomain;
|
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.command.ConsoleCommandSender;
|
||||||
import net.md_5.bungee.config.Configuration;
|
import net.md_5.bungee.config.Configuration;
|
||||||
import net.md_5.bungee.config.YamlConfig;
|
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.BanList;
|
||||||
import net.md_5.bungee.eaglercraft.DomainBlacklist;
|
import net.md_5.bungee.eaglercraft.DomainBlacklist;
|
||||||
import net.md_5.bungee.eaglercraft.PluginEaglerSkins;
|
import net.md_5.bungee.eaglercraft.PluginEaglerSkins;
|
||||||
|
@ -126,6 +128,7 @@ public class BungeeCord extends ProxyServer {
|
||||||
private ConsoleReader consoleReader;
|
private ConsoleReader consoleReader;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private Collection<Command> banCommands;
|
private Collection<Command> banCommands;
|
||||||
|
public AuthSystem authSystem;
|
||||||
|
|
||||||
public static BungeeCord getInstance() {
|
public static BungeeCord getInstance() {
|
||||||
return (BungeeCord) ProxyServer.getInstance();
|
return (BungeeCord) ProxyServer.getInstance();
|
||||||
|
@ -234,7 +237,10 @@ public class BungeeCord extends ProxyServer {
|
||||||
this.pluginManager.detectPlugins(this.pluginsFolder);
|
this.pluginManager.detectPlugins(this.pluginsFolder);
|
||||||
this.pluginManager.addInternalPlugin(new PluginEaglerSkins());
|
this.pluginManager.addInternalPlugin(new PluginEaglerSkins());
|
||||||
this.pluginManager.addInternalPlugin(new PluginEaglerVoice(this.config.getVoiceEnabled()));
|
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) {
|
if (this.reconnectHandler == null) {
|
||||||
this.reconnectHandler = new SQLReconnectHandler();
|
this.reconnectHandler = new SQLReconnectHandler();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class ServerConnection implements Server {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void disconnect(final String reason) {
|
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.unsafe().sendPacket(new PacketFFKick(reason));
|
||||||
this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() {
|
this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,7 +41,7 @@ public class ServerConnection implements Server {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InetSocketAddress getAddress() {
|
public InetSocketAddress getAddress() {
|
||||||
return this.getInfo().getAddress();
|
return this.getInfo() == null ? null : this.getInfo().getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,7 +54,7 @@ public class ServerConnection implements Server {
|
||||||
this.unsafe = new Connection.Unsafe() {
|
this.unsafe = new Connection.Unsafe() {
|
||||||
@Override
|
@Override
|
||||||
public void sendPacket(final DefinedPacket packet) {
|
public void sendPacket(final DefinedPacket packet) {
|
||||||
ServerConnection.this.ch.write(packet);
|
if (ServerConnection.this.ch != null) ServerConnection.this.ch.write(packet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.ch = ch;
|
this.ch = ch;
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
package net.md_5.bungee.api.config;
|
package net.md_5.bungee.api.config;
|
||||||
|
|
||||||
import java.io.File;
|
import java.util.List;
|
||||||
|
|
||||||
public class AuthServiceInfo {
|
public class AuthServiceInfo {
|
||||||
|
|
||||||
private final boolean enabled;
|
private final boolean enabled;
|
||||||
private final String limbo;
|
private final String authfile;
|
||||||
private final File authfile;
|
private final int ipLimit;
|
||||||
private final int timeout;
|
private final List<String> joinMessages;
|
||||||
|
|
||||||
public AuthServiceInfo(boolean enabled, String limbo, File authfile, int timeout) {
|
public AuthServiceInfo(boolean enabled, String authfile, int timeout, List<String> joinMessages) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
this.limbo = limbo;
|
|
||||||
this.authfile = authfile;
|
this.authfile = authfile;
|
||||||
this.timeout = timeout;
|
this.ipLimit = timeout;
|
||||||
|
this.joinMessages = joinMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLimbo() {
|
public String getAuthfile() {
|
||||||
return limbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getAuthfile() {
|
|
||||||
return authfile;
|
return authfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTimeout() {
|
public int getIpLimit() {
|
||||||
return timeout;
|
return ipLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getJoinMessages() {
|
||||||
|
return joinMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <oldPassword> <newPassword>");
|
||||||
|
} 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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -69,13 +70,15 @@ public class YamlConfig implements ConfigurationAdapter {
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException("Could not load configuration!", ex);
|
throw new RuntimeException("Could not load configuration!", ex);
|
||||||
}
|
}
|
||||||
final Map<String, Object> permissions = this.get("permissions", new HashMap<String, Object>());
|
final Map<String, List<String>> permissions = this.get("permissions", new HashMap<String, List<String>>());
|
||||||
if (permissions.isEmpty()) {
|
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",
|
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.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.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"));
|
"bungeecord.command.eag.blockdomain", "bungeecord.command.eag.blockdomainname", "bungeecord.command.eag.unblockdomain"));
|
||||||
|
} else if (this.get("authservice", new HashMap<String, Object>()).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<String, Object>());
|
this.get("groups", new HashMap<String, Object>());
|
||||||
}
|
}
|
||||||
|
@ -275,9 +278,10 @@ 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", true, auth), this.get("limbo", "lobby", auth), new File(this.get("authfile", "passwords.yml", auth)), this.get("timeout", 30, auth));
|
final List<String> defaultJoinMessages = new ArrayList<String>();
|
||||||
return null;
|
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
|
@Override
|
||||||
|
|
|
@ -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.LoginEvent;
|
||||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
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;
|
||||||
import net.md_5.bungee.eaglercraft.BanList.BanCheck;
|
import net.md_5.bungee.eaglercraft.BanList.BanCheck;
|
||||||
import net.md_5.bungee.eaglercraft.BanList.BanState;
|
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.PacketHandler;
|
||||||
import net.md_5.bungee.netty.PipelineUtils;
|
import net.md_5.bungee.netty.PipelineUtils;
|
||||||
import net.md_5.bungee.protocol.Forge;
|
import net.md_5.bungee.protocol.Forge;
|
||||||
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
import net.md_5.bungee.protocol.packet.*;
|
||||||
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;
|
|
||||||
|
|
||||||
public class InitialHandler extends PacketHandler implements PendingConnection {
|
public class InitialHandler extends PacketHandler implements PendingConnection {
|
||||||
private final ProxyServer bungee;
|
private final ProxyServer bungee;
|
||||||
|
@ -259,10 +252,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
|
||||||
userCon.getAttachment().put("origin", origin);
|
userCon.getAttachment().put("origin", origin);
|
||||||
}
|
}
|
||||||
userCon.init();
|
userCon.init();
|
||||||
this.bungee.getPluginManager().callEvent(new PostLoginEvent(userCon));
|
HandlerBoss handlerBoss = ((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class));
|
||||||
((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class)).setHandler(new UpstreamBridge(this.bungee, userCon));
|
if (BungeeCord.getInstance().config.getAuthInfo().isEnabled()) {
|
||||||
final ServerInfo server = this.bungee.getReconnectHandler().getServer(userCon);
|
handlerBoss.setHandler(new AuthHandler(this.bungee, userCon, handlerBoss));
|
||||||
userCon.connect(server, true);
|
} 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;
|
this.thisState = State.FINISHED;
|
||||||
throw new CancelSendSignal();
|
throw new CancelSendSignal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class UpstreamBridge extends PacketHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handle(final byte[] buf) throws Exception {
|
public void handle(final byte[] buf) throws Exception {
|
||||||
EntityMap.rewrite(buf, this.con.getClientEntityId(), this.con.getServerEntityId());
|
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);
|
this.con.getServer().getCh().write(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <password>");
|
||||||
|
} else {
|
||||||
|
this.con.sendMessage("\u00A7cPlease register to continue! /register <password> <confirmPassword>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 <password>");
|
||||||
|
} 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() + " <password> <confirmPassword>");
|
||||||
|
} 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() + " <oldPassword> <newPassword>");
|
||||||
|
} 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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String> 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<String, AuthData> 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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ProxiedPlayer> 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"));
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -55,4 +55,7 @@ public abstract class AbstractPacketHandler {
|
||||||
|
|
||||||
public void handle(final PacketFFKick kick) throws Exception {
|
public void handle(final PacketFFKick kick) throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handle(final Packet0DPositionAndLook positionAndLook) throws Exception {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user