diff --git a/pom.xml b/pom.xml index 3f5db04..478663e 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ eddsa 0.3.0 - + org.apache.mina mina-core @@ -84,7 +84,7 @@ slf4j-api 1.7.28 - + org.slf4j slf4j-jdk14 @@ -117,6 +117,21 @@ 1.10 provided + + commons-lang + commons-lang + 2.6 + + + net.md-5 + bungeecord-bootstrap + 1.13-SNAPSHOT + + + org.projectlombok + lombok + 1.18.4 + @@ -156,7 +171,7 @@ - + org.apache.maven.plugins diff --git a/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java b/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java index d054204..59185c6 100644 --- a/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java +++ b/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java @@ -19,8 +19,8 @@ public class ConfigPasswordAuthenticator implements PasswordAuthenticator { public boolean authenticate(String username, String password, ServerSession ss) { // Depending on our hash type, we have to try and figure out what we're doing. - String HashType = SshdPlugin.instance.getConfig().getString("PasswordType"); - String ConfigHash = SshdPlugin.instance.getConfig().getString("Credentials." + username.trim()); + String HashType = SshdPlugin.instance.configuration.getString("PasswordType"); + String ConfigHash = SshdPlugin.instance.configuration.getString("Credentials." + username.trim()); if (ConfigHash == null) SshdPlugin.instance.getLogger().warning("Config has no such user: " + username); @@ -70,7 +70,7 @@ public class ConfigPasswordAuthenticator implements PasswordAuthenticator { } SshdPlugin.instance.getLogger().info("Failed login for " + username + " using " + HashType + "-based password authentication."); - Integer tries = SshdPlugin.instance.getConfig().getInt("LoginRetries"); + Integer tries = SshdPlugin.instance.configuration.getInt("LoginRetries"); try { diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleCommandCompleter.java b/src/main/java/com/ryanmichela/sshd/ConsoleCommandCompleter.java index 182a235..c56dc61 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleCommandCompleter.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleCommandCompleter.java @@ -5,15 +5,18 @@ package com.ryanmichela.sshd; */ import jline.console.completer.Completer; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandMap; + import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -public class ConsoleCommandCompleter implements Completer { +// This class *may* not be needed. +// If it is needed, the only class that uses it is ConsoleShellFactory on line 96 +public class ConsoleCommandCompleter /*implements Completer*/ { + + /* public int complete(final String buffer, final int cursor, final List candidates) { Waitable> waitable = new Waitable>() { @Override @@ -22,7 +25,7 @@ public class ConsoleCommandCompleter implements Completer { return commandMap.tabComplete(Bukkit.getServer().getConsoleSender(), buffer); } }; - Bukkit.getScheduler().runTask(SshdPlugin.instance, waitable); + SshdPlugin.instance.getProxy().getScheduler().runAsync(SshdPlugin.instance, waitable); try { List offers = waitable.get(); if (offers == null) { @@ -43,5 +46,6 @@ public class ConsoleCommandCompleter implements Completer { } return cursor; } + */ } diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleCommandFactory.java b/src/main/java/com/ryanmichela/sshd/ConsoleCommandFactory.java index 2d5b19c..00f2f92 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleCommandFactory.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleCommandFactory.java @@ -55,12 +55,19 @@ public class ConsoleCommandFactory implements CommandFactory { try { SshdPlugin.instance.getLogger() .info("[U: " + environment.getEnv().get(Environment.ENV_USER) + "] " + command); - - SshdPlugin.instance.getProxy().getPluginManager().dispatchCommand(SshdPlugin.instance.getProxy().getConsoleSender().getInstance(), command); + + SshdPlugin.instance.getProxy().getPluginManager().dispatchCommand(SshdPlugin.instance.getProxy().getConsole(), command); + + // getConsoleSender() doesn't exist in bungee, and is replaced with getConsole() from my understanding. + //SshdPlugin.instance.getProxy().getPluginManager().dispatchCommand(SshdPlugin.instance.getProxy().getConsoleSender().getInstance(), command); //Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); - } catch (Exception e) { + } + catch (Exception e) + { SshdPlugin.instance.getLogger().severe("Error processing command from SSH -" + e.getMessage()); - } finally { + } + finally + { callback.onExit(0); } } diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleLogFormatter.java b/src/main/java/com/ryanmichela/sshd/ConsoleLogFormatter.java index 629afce..1f28dcd 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleLogFormatter.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleLogFormatter.java @@ -4,7 +4,7 @@ package com.ryanmichela.sshd; * Copyright 2013 Ryan Michela */ -import org.bukkit.ChatColor; +import net.md_5.bungee.api.ChatColor; import org.fusesource.jansi.Ansi; import java.io.PrintWriter; diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java index 34fb93e..5770529 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java @@ -10,6 +10,7 @@ import com.ryanmichela.sshd.StreamHandlerAppender; import com.ryanmichela.sshd.implementations.SSHDCommandSender; import com.ryanmichela.sshd.ConsoleLogFormatter; import jline.console.ConsoleReader; +import net.md_5.bungee.api.config.ServerInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; import org.apache.sshd.common.Factory; @@ -18,7 +19,6 @@ import org.apache.sshd.server.command.Command; import org.apache.sshd.server.channel.ChannelSession; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; -import org.bukkit.Bukkit; import java.io.File; import java.io.FileNotFoundException; @@ -32,6 +32,8 @@ import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.StreamHandler; +import static com.ryanmichela.sshd.SshdPlugin.instance; + public class ConsoleShellFactory implements ShellFactory { public Command createShell(ChannelSession cs) { @@ -91,7 +93,7 @@ public class ConsoleShellFactory implements ShellFactory { { this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal()); this.ConsoleReader.setExpandEvents(true); - this.ConsoleReader.addCompleter(new ConsoleCommandCompleter()); + //this.ConsoleReader.addCompleter(new ConsoleCommandCompleter()); StreamHandler streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader); this.streamHandlerAppender = new StreamHandlerAppender(streamHandler); @@ -118,7 +120,7 @@ public class ConsoleShellFactory implements ShellFactory { { try { - if (!SshdPlugin.instance.getConfig().getString("Mode").equals("RPC")) + if (!instance.configuration.getString("Mode").equals("RPC")) printPreamble(this.ConsoleReader); while (true) { @@ -141,22 +143,22 @@ public class ConsoleShellFactory implements ShellFactory { // Hide the mkpasswd command input from other users. Boolean mkpasswd = command.split(" ")[0].equals("mkpasswd"); - Bukkit.getScheduler().runTask( - SshdPlugin.instance, () -> + instance.getProxy().getScheduler().runAsync( + instance, () -> { - if (SshdPlugin.instance.getConfig().getString("Mode").equals("RPC") && command.startsWith("rpc")) + if (instance.configuration.getString("Mode").equals("RPC") && command.startsWith("rpc")) { // NO ECHO NO PREAMBLE AND SHIT String cmd = command.substring("rpc".length() + 1, command.length()); - SshdPlugin.instance.getProxy().getPluginManager().dispatchCommand(this.SshdCommandSender, cmd); + instance.getProxy().getPluginManager().dispatchCommand(this.SshdCommandSender, cmd); //Bukkit.dispatchCommand(this.SshdCommandSender, cmd); } else { if (!mkpasswd) - SshdPlugin.instance.getLogger().info("<" + this.Username + "> " + command); - - SshdPlugin.instance.getProxy().getPluginManager().dispatchCommand(SshdPlugin.instance.getProxy().getConsoleSender().getInstance(), command); + instance.getLogger().info("<" + this.Username + "> " + command); + + instance.getProxy().getPluginManager().dispatchCommand(instance.getProxy().getConsole(), command); //Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); } }); @@ -164,18 +166,18 @@ public class ConsoleShellFactory implements ShellFactory { } catch (IOException e) { - SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error processing command from SSH", e); + instance.getLogger().log(Level.SEVERE, "Error processing command from SSH", e); } finally { - SshdPlugin.instance.getLogger().log(Level.INFO, this.Username + " disconnected from SSH."); + instance.getLogger().log(Level.INFO, this.Username + " disconnected from SSH."); callback.onExit(0); } } private void printPreamble(ConsoleReader cr) throws IOException { - File f = new File(SshdPlugin.instance.getDataFolder(), "motd.txt"); + File f = new File(instance.getDataFolder(), "motd.txt"); try { BufferedReader br = new BufferedReader(new FileReader(f)); @@ -186,16 +188,18 @@ public class ConsoleShellFactory implements ShellFactory { } catch (FileNotFoundException e) { - SshdPlugin.instance.getLogger().log(Level.WARNING, "Could not open " + f + ": File does not exist."); + instance.getLogger().log(Level.WARNING, "Could not open " + f + ": File does not exist."); // Not showing the SSH motd is not a fatal failure, let the session continue. } // Doesn't really guarantee our actual system hostname but // it's better than not having one at all. cr.println("Connected to: " + InetAddress.getLocalHost().getHostName() + " (BungeeCord)\r"); - cr.println(ConsoleLogFormatter.ColorizeString(DO SOMETHING HERE).replaceAll("\n", "\r\n")); + // Since BungeeCord is stupid, we have to parse the config file and the the MOTD from it that way... + // If you try to use the method getMotd() it returns that it can't be referenced from a non-static context, which is stupid. + cr.println(ConsoleLogFormatter.ColorizeString(instance.configuration.getString("motd")).replaceAll("\n", "\r\n")); cr.println("\r"); - cr.println("Type 'exit' to exit the shell." + "\r"); + cr.println("Type 'exit' or press Ctrl+D exit the shell." + "\r"); cr.println("===============================================" + "\r"); } } diff --git a/src/main/java/com/ryanmichela/sshd/MkpasswdCommand.java b/src/main/java/com/ryanmichela/sshd/MkpasswdCommand.java index 60cdc66..7369374 100644 --- a/src/main/java/com/ryanmichela/sshd/MkpasswdCommand.java +++ b/src/main/java/com/ryanmichela/sshd/MkpasswdCommand.java @@ -1,15 +1,67 @@ package com.ryanmichela.sshd; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.Command; -import org.bukkit.entity.Player; - import java.util.Arrays; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Command; + import com.ryanmichela.sshd.Cryptography; import com.ryanmichela.sshd.SshdPlugin; +public class MkpasswdCommand extends Command +{ + + public MkpasswdCommand() + { + super("mkpasswd"); + } + + @Override + public void execute(CommandSender sender, String[] args) + { + ProxiedPlayer player = (ProxiedPlayer) sender; + + String algoritm, password; + algoritm = args[0]; + password = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); + try + { + // Stupid bukkit, we have to concatenate the arguments together if they're using + // spaces in their passwords otherwise it won't be as strong as it should be. + + } + catch (ArrayIndexOutOfBoundsException e) + { + // ignore it. + } + + // If they're console, allow regardless. + try + { + if (player.hasPermission("sshd.mkpasswd")) + { + // Dumb but whatever. Some people are really dense. + if (algoritm.equalsIgnoreCase("PLAIN")) + sender.sendMessage(password); + else if (algoritm.equalsIgnoreCase("pbkdf2")) + sender.sendMessage(Cryptography.PBKDF2_HashPassword(password)); + else if (algoritm.equalsIgnoreCase("bcrypt")) + sender.sendMessage(Cryptography.BCrypt_HashPassword(password)); + else if (algoritm.equalsIgnoreCase("sha256")) + sender.sendMessage(Cryptography.SHA256_HashPassword(password)); + } + } + catch (Exception e) + { + // since this is a player, send a failure message + sender.sendMessage("An error occured, please check console."); + e.printStackTrace(); + } + } +} + +/* class MkpasswdCommand implements CommandExecutor { @Override @@ -96,4 +148,4 @@ class MkpasswdCommand implements CommandExecutor } return false; } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java b/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java index 36b5027..ffb369a 100644 --- a/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java +++ b/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java @@ -1,5 +1,6 @@ package com.ryanmichela.sshd; +import net.md_5.bungee.config.Configuration; import org.apache.commons.lang.ArrayUtils; import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; import org.apache.sshd.common.config.keys.PublicKeyEntryResolver; @@ -20,14 +21,13 @@ public class PublicKeyAuthenticator implements PublickeyAuthenticator { private File authorizedKeysDir; private Map FailCounts = new HashMap(); - public PublicKeyAuthenticator(File authorizedKeysDir) { this.authorizedKeysDir = authorizedKeysDir; } @Override public boolean authenticate(String username, PublicKey key, ServerSession session) { byte[] keyBytes = key.getEncoded(); File keyFile = new File(authorizedKeysDir, username); - Integer tries = SshdPlugin.instance.getConfig().getInt("LoginRetries"); + Integer tries = SshdPlugin.instance.configuration.getInt("LoginRetries"); if (keyFile.exists()) { diff --git a/src/main/java/com/ryanmichela/sshd/SshdPlugin.java b/src/main/java/com/ryanmichela/sshd/SshdPlugin.java index ed8f3f6..1e44f8a 100644 --- a/src/main/java/com/ryanmichela/sshd/SshdPlugin.java +++ b/src/main/java/com/ryanmichela/sshd/SshdPlugin.java @@ -1,11 +1,15 @@ package com.ryanmichela.sshd; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.config.ConfigurationProvider; +import net.md_5.bungee.config.YamlConfiguration; import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; import org.apache.sshd.server.SshServer; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.api.config.*; import com.ryanmichela.sshd.ConsoleShellFactory; import com.ryanmichela.sshd.MkpasswdCommand; @@ -25,10 +29,14 @@ public final class SshdPlugin extends Plugin { private SshServer sshd; public static SshdPlugin instance; + private File file; + public Configuration configuration; + @Override public void onLoad() { - saveDefaultConfig(); + file = new File(ProxyServer.getInstance().getPluginsFolder()+ "/config.yml"); + File authorizedKeys = new File(getDataFolder(), "authorized_keys"); if (!authorizedKeys.exists()) authorizedKeys.mkdirs(); @@ -47,10 +55,32 @@ public final class SshdPlugin extends Plugin e.printStackTrace(); } + + try + { + if (!file.exists()) + { + file.createNewFile(); + } + configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file); + + // more testing + configuration.set("test", "This configuration file works!"); + ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration,file); + } + catch (IOException e) + { + e.printStackTrace(); + } + // Don't go any lower than INFO or SSHD will cause a stack overflow exception. // SSHD will log that it wrote bites to the output stream, which writes // bytes to the output stream - ad nauseaum. getLogger().setLevel(Level.INFO); + + // config testing + String printout = configuration.getString("test"); + getLogger().info(printout); } @Override public void onEnable() @@ -58,8 +88,8 @@ public final class SshdPlugin extends Plugin instance = this; sshd = SshServer.setUpDefaultServer(); - sshd.setPort(getConfig().getInt("Port", 1025)); - String host = getConfig().getString("ListenAddress", "all"); + sshd.setPort(configuration.getInt("Port", 1025)); + String host = configuration.getString("ListenAddress", "all"); sshd.setHost(host.equals("all") ? null : host); File hostKey = new File(getDataFolder(), "hostkey"); @@ -70,14 +100,15 @@ public final class SshdPlugin extends Plugin sshd.setPasswordAuthenticator(new ConfigPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new PublicKeyAuthenticator(authorizedKeys)); - if (getConfig().getBoolean("EnableSFTP")) + if (configuration.getBoolean("EnableSFTP")) { sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory())); sshd.setFileSystemFactory( new VirtualFileSystemFactory(FileSystems.getDefault().getPath(getDataFolder().getAbsolutePath()).getParent().getParent())); } - this.getCommand("mkpasswd").setExecutor(new MkpasswdCommand()); + getProxy().getPluginManager().registerCommand(this, new MkpasswdCommand()); + //this.getCommand("mkpasswd").setExecutor(new MkpasswdCommand()); sshd.setCommandFactory(new ConsoleCommandFactory()); try @@ -101,4 +132,12 @@ public final class SshdPlugin extends Plugin // do nothing } } + + public static SshdPlugin getInstance() { + return instance; + } + + private static void setInstance(SshdPlugin instance) { + SshdPlugin.instance = instance; + } } diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java index 654c6c8..7a21b5d 100644 --- a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java @@ -1,7 +1,9 @@ package com.ryanmichela.sshd.implementations; import com.ryanmichela.sshd.SshdPlugin; -import net.md_5.bungee.command.ConsoleCommandSender; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; @@ -26,14 +28,15 @@ import com.ryanmichela.sshd.ConsoleShellFactory; import java.io.IOException; import java.util.Arrays; -import java.util.Set; +import java.util.Collection; +import java.util.Collections; import java.util.logging.Level; @NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class SSHDConsoleCommandSender implements CommandSender -{ - @Getter - private static final SSHDConsoleCommandSender instance = new SSHDConsoleCommandSender(); +public final class SSHDCommandSender implements CommandSender { + private static final SSHDCommandSender instance = new SSHDCommandSender(); + + public ConsoleShellFactory.ConsoleShell console; @Override public void sendMessage(String message) { diff --git a/src/main/java/com/ryanmichela/sshd/sshd1/SshdPlugin.java b/src/main/java/com/ryanmichela/sshd/sshd1/SshdPlugin.java new file mode 100644 index 0000000..6a0682c --- /dev/null +++ b/src/main/java/com/ryanmichela/sshd/sshd1/SshdPlugin.java @@ -0,0 +1,16 @@ +package com.ryanmichela.sshd.sshd1; + +import net.md_5.bungee.api.plugin.Plugin; + +public final class SshdPlugin extends Plugin { + + @Override + public void onEnable() { + // Plugin startup logic + } + + @Override + public void onDisable() { + // Plugin shutdown logic + } +}