diff --git a/src/main/java/me/totalfreedom/totalfreedommod/LogViewer.java b/src/main/java/me/totalfreedom/totalfreedommod/LogViewer.java index 018299a3..161f7bf9 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/LogViewer.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/LogViewer.java @@ -1,15 +1,13 @@ package me.totalfreedom.totalfreedommod; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; +import java.io.UnsupportedEncodingException; +import java.net.*; +import java.security.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import me.totalfreedom.totalfreedommod.admin.Admin; -import me.totalfreedom.totalfreedommod.command.Command_logs; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.util.FLog; import org.apache.commons.lang3.StringUtils; @@ -38,10 +36,10 @@ public class LogViewer extends FreedomService public void updateLogsRegistration(final CommandSender sender, final Player target, final LogsRegistrationMode mode) { - updateLogsRegistration(sender, target.getName(), target.getAddress().getAddress().getHostAddress().trim(), mode); + updateLogsRegistration(sender, target.getName(), mode); } - public void updateLogsRegistration(final CommandSender sender, final String targetName, final String targetIP, final LogsRegistrationMode mode) + public void updateLogsRegistration(final CommandSender sender, final String targetName, final LogsRegistrationMode mode) { final String logsRegisterUrl = ConfigEntry.LOGS_URL.getString(); final String logsRegisterPassword = ConfigEntry.LOGS_SECRET.getString(); @@ -63,14 +61,16 @@ public class LogViewer extends FreedomService sender.sendMessage(ChatColor.YELLOW + "Connecting..."); } - URL url = new URLBuilder(logsRegisterUrl) - .addQueryParameter("mode", mode.toString()) + final String key = SecureCodeGenerator.generateCode(20); + + final URL urlAdd = new URLBuilder(logsRegisterUrl) + .addQueryParameter("mode", mode.name()) .addQueryParameter("password", logsRegisterPassword) .addQueryParameter("name", targetName) - .addQueryParameter("ip", targetIP) + .addQueryParameter("key", key) .getURL(); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + final HttpURLConnection connection = (HttpURLConnection) urlAdd.openConnection(); connection.setConnectTimeout(1000 * 5); connection.setReadTimeout(1000 * 5); connection.setUseCaches(false); @@ -92,7 +92,29 @@ public class LogViewer extends FreedomService { if (responseCode == 200) { - sender.sendMessage(ChatColor.GREEN + "Registration " + mode.toString() + "d."); + if (mode == LogsRegistrationMode.ADD) + { + String link = null; + try + { + final URL urlVerify = new URLBuilder(logsRegisterUrl) + .addQueryParameter("mode", LogsRegistrationMode.VERIFY.name()) + .addQueryParameter("name", targetName) + .addQueryParameter("key", key) + .getURL(); + link = urlVerify.toString(); + } + catch (Exception ex) + { + FLog.severe(ex); + } + + sender.sendMessage(ChatColor.GREEN + "Open this link to verify your logviewer registration:\n" + ChatColor.DARK_GREEN + link); + } + else + { + sender.sendMessage(ChatColor.GREEN + "Logviewer access revoked successfully."); + } } else { @@ -110,30 +132,10 @@ public class LogViewer extends FreedomService }.runTaskAsynchronously(plugin); } - public void deactivateSuperadmin(Admin superadmin) - { - for (String ip : superadmin.getIps()) - { - updateLogsRegistration(null, superadmin.getName(), ip, LogsRegistrationMode.DELETE); - } - } - public static enum LogsRegistrationMode { - UPDATE("update"), DELETE("delete"); - private final String mode; - - private LogsRegistrationMode(String mode) - { - this.mode = mode; - } - - @Override - public String toString() - { - return mode; - } + ADD, DELETE, VERIFY; } private static class URLBuilder @@ -160,11 +162,44 @@ public class LogViewer extends FreedomService while (it.hasNext()) { Map.Entry pair = it.next(); - pairs.add(pair.getKey() + "=" + pair.getValue()); + try + { + pairs.add(URLEncoder.encode(pair.getKey(), "UTF-8") + "=" + URLEncoder.encode(pair.getValue(), "UTF-8")); + } + catch (UnsupportedEncodingException ex) + { + FLog.severe(ex); + } } return new URL(requestPath + "?" + StringUtils.join(pairs, "&")); } } + private static class SecureCodeGenerator + { + + private static final String CHARACTER_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + public static String generateCode(final int length) + { + SecureRandom random; + try + { + random = SecureRandom.getInstance("SHA1PRNG", "SUN"); + } + catch (NoSuchAlgorithmException | NoSuchProviderException ex) + { + random = new SecureRandom(); + FLog.severe(ex); + } + + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) + { + sb.append(CHARACTER_SET.charAt(random.nextInt(CHARACTER_SET.length()))); + } + return sb.toString(); + } + } } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java b/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java index b27625b4..35b61d63 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java @@ -5,6 +5,8 @@ import java.util.Date; import java.util.List; import lombok.Getter; import lombok.Setter; +import me.totalfreedom.totalfreedommod.LogViewer.LogsRegistrationMode; +import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.util.FUtil; import net.pravian.aero.base.ConfigLoadable; @@ -25,7 +27,6 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable @Setter private String name; @Getter - @Setter private boolean active = true; @Getter @Setter @@ -138,6 +139,26 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable ips.clear(); } + public void setActive(boolean active) + { + this.active = active; + + final TotalFreedomMod plugin = TotalFreedomMod.plugin(); + + if (!active) + { + if (getRank().isAtLeast(Rank.TELNET_ADMIN)) + { + if (plugin.btb != null) + { + plugin.btb.killTelnetSessions(getName()); + } + } + + plugin.lv.updateLogsRegistration(null, getName(), LogsRegistrationMode.DELETE); + } + } + @Override public boolean isValid() { diff --git a/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java b/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java index b40bca8e..95872050 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java @@ -10,7 +10,6 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.TotalFreedomMod; -import me.totalfreedom.totalfreedommod.command.Command_logs; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.util.FLog; @@ -272,6 +271,14 @@ public class AdminList extends FreedomService public boolean removeAdmin(Admin admin) { + if (admin.getRank().isAtLeast(Rank.TELNET_ADMIN)) + { + if (plugin.btb != null) + { + plugin.btb.killTelnetSessions(admin.getName()); + } + } + // Remove admin, update views if (allAdmins.remove(admin.getConfigKey()) == null) { @@ -345,7 +352,6 @@ public class AdminList extends FreedomService } admin.setActive(false); - plugin.lv.deactivateSuperadmin(admin); } save(); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/bridge/BukkitTelnetBridge.java b/src/main/java/me/totalfreedom/totalfreedommod/bridge/BukkitTelnetBridge.java index 894c4789..0293ad5a 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/bridge/BukkitTelnetBridge.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/bridge/BukkitTelnetBridge.java @@ -1,21 +1,29 @@ package me.totalfreedom.totalfreedommod.bridge; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Map; +import me.totalfreedom.bukkittelnet.BukkitTelnet; import me.totalfreedom.bukkittelnet.api.TelnetCommandEvent; import me.totalfreedom.bukkittelnet.api.TelnetPreLoginEvent; import me.totalfreedom.bukkittelnet.api.TelnetRequestDataTagsEvent; +import me.totalfreedom.bukkittelnet.session.ClientSession; import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.rank.Rank; +import me.totalfreedom.totalfreedommod.util.FLog; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.plugin.Plugin; public class BukkitTelnetBridge extends FreedomService { + private BukkitTelnet bukkitTelnetPlugin = null; + public BukkitTelnetBridge(TotalFreedomMod plugin) { super(plugin); @@ -94,4 +102,69 @@ public class BukkitTelnetBridge extends FreedomService playerTags.put("tfm.essentialsBridge.getNickname", plugin.esb.getNickname(player.getName())); } } + + public BukkitTelnet getBukkitTelnetPlugin() + { + if (bukkitTelnetPlugin == null) + { + try + { + final Plugin bukkitTelnet = server.getPluginManager().getPlugin("BukkitTelnet"); + if (bukkitTelnet != null) + { + if (bukkitTelnet instanceof BukkitTelnet) + { + bukkitTelnetPlugin = (BukkitTelnet) bukkitTelnet; + } + } + } + catch (Exception ex) + { + FLog.severe(ex); + } + } + + return bukkitTelnetPlugin; + } + + public void killTelnetSessions(final String name) + { + try + { + final List sessionsToRemove = new ArrayList<>(); + + final BukkitTelnet telnet = getBukkitTelnetPlugin(); + if (telnet != null) + { + final Iterator it = telnet.appender.getSessions().iterator(); + while (it.hasNext()) + { + final ClientSession session = it.next(); + if (name != null && name.equalsIgnoreCase(session.getUserName())) + { + sessionsToRemove.add(session); + } + } + + for (final ClientSession session : sessionsToRemove) + { + try + { + telnet.appender.removeSession(session); + session.syncTerminateSession(); + } + catch (Exception ex) + { + FLog.severe("Error removing single telnet session: " + ex.getMessage()); + } + } + + FLog.info(sessionsToRemove.size() + " telnet session(s) removed."); + } + } + catch (Exception ex) + { + FLog.severe("Error removing telnet sessions: " + ex.getMessage()); + } + } } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_logs.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_logs.java index a2056297..5fae0ac8 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_logs.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_logs.java @@ -1,26 +1,10 @@ package me.totalfreedom.totalfreedommod.command; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import me.totalfreedom.totalfreedommod.LogViewer.LogsRegistrationMode; -import me.totalfreedom.totalfreedommod.TotalFreedomMod; -import me.totalfreedom.totalfreedommod.admin.Admin; -import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.rank.Rank; -import me.totalfreedom.totalfreedommod.util.FLog; -import org.apache.commons.lang3.StringUtils; -import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; @CommandPermissions(level = Rank.SUPER_ADMIN, source = SourceType.ONLY_IN_GAME) @CommandParameters(description = "Register your connection with the TFM logviewer.", usage = "/ [off]") @@ -30,16 +14,13 @@ public class Command_logs extends FreedomCommand @Override public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) { - LogsRegistrationMode mode = LogsRegistrationMode.UPDATE; - - if (args.length == 1) + LogsRegistrationMode mode = LogsRegistrationMode.ADD; + if (args.length == 1 && "off".equalsIgnoreCase(args[0])) { - mode = ("off".equals(args[0]) ? LogsRegistrationMode.DELETE : LogsRegistrationMode.UPDATE); + mode = LogsRegistrationMode.DELETE; } - plugin.lv.updateLogsRegistration(sender, playerSender, mode); return true; } - }