From 0635ea7a35ee1908bb49af2e6e70ba9bd4b49620 Mon Sep 17 00:00:00 2001 From: Justin Crawford Date: Thu, 3 Oct 2019 21:07:00 -0700 Subject: [PATCH] Fixed a bug (open on the upstream fork), also rewote config. Fixed a bug that caused sessions to get overwritten and some of them would seem to freeze, the whole thing relied on undefined behavior. This bug was a static variable that copied sessions all around globally. Rewrote the config to support a few more options (the PasswordType is coming soon) and explained how the new authorized_users files work. Public key authentication now has the same number of retires that password authentication has (this aligns with how OpenSSH does it) and the number of retries can now be configured in the configuration. --- pom.xml | 2 + .../sshd/ConfigPasswordAuthenticator.java | 56 +++-- .../ryanmichela/sshd/ConsoleShellFactory.java | 225 +++++++++--------- .../sshd/PublicKeyAuthenticator.java | 51 ++-- .../java/com/ryanmichela/sshd/SshdPlugin.java | 6 +- .../implementations/SSHDCommandSender.java | 166 +++++++------ .../SSHDConversationTracker.java | 104 ++++---- src/main/resources/config.yml | 31 ++- 8 files changed, 337 insertions(+), 304 deletions(-) diff --git a/pom.xml b/pom.xml index b126ae3..c3873fd 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,8 @@ org.apache.sshd sshd-common 2.3.0 + compile + jar diff --git a/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java b/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java index 4f850c2..37202da 100644 --- a/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java +++ b/src/main/java/com/ryanmichela/sshd/ConfigPasswordAuthenticator.java @@ -11,30 +11,38 @@ import java.util.Map; */ public class ConfigPasswordAuthenticator implements PasswordAuthenticator { - private Map failCounts = new HashMap(); + private Map FailCounts = new HashMap(); - @Override - public boolean authenticate(String username, String password, ServerSession serverSession) { - if (SshdPlugin.instance.getConfig().getString("credentials." + username).equals(password)) { - failCounts.put(username, 0); - return true; - } - SshdPlugin.instance.getLogger().info("Failed login for " + username + " using password authentication."); + @Override + public boolean authenticate(String username, String password, ServerSession ss) + { + if (SshdPlugin.instance.getConfig().getString("Credentials." + username).equals(password)) + { + FailCounts.put(username, 0); + return true; + } + SshdPlugin.instance.getLogger().info("Failed login for " + username + " using password authentication."); - try { - Thread.sleep(3000); - if (failCounts.containsKey(username)) { - failCounts.put(username, failCounts.get(username) + 1); - } else { - failCounts.put(username, 1); - } - if (failCounts.get(username) >= 3) { - failCounts.put(username, 0); - serverSession.close(true); - } - } catch (InterruptedException e) { - // do nothing - } - return false; - } + Integer tries = SshdPlugin.instance.getConfig().getInt("LoginRetries"); + + try + { + Thread.sleep(3000); + if (this.FailCounts.containsKey(username)) + this.FailCounts.put(username, this.FailCounts.get(username) + 1); + else + this.FailCounts.put(username, 1); + + if (this.FailCounts.get(username) >= tries) + { + this.FailCounts.put(username, 0); + ss.close(true); + } + } + catch (InterruptedException e) + { + // do nothing + } + return false; + } } diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java index aab350e..de9900c 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java @@ -27,137 +27,140 @@ import java.util.logging.StreamHandler; public class ConsoleShellFactory implements ShellFactory { - static SSHDCommandSender sshdCommandSender = new SSHDCommandSender(); + public Command createShell(ChannelSession cs) { + return new ConsoleShell(); + } - public Command createShell(ChannelSession cs) { - return new ConsoleShell(); - } + public class ConsoleShell implements Command, Runnable { - public static class ConsoleShell implements Command, Runnable { + private InputStream in; + private OutputStream out; + private OutputStream err; + private ExitCallback callback; + private Environment environment; + private Thread thread; + private String Username; - private InputStream in; - private OutputStream out; - private OutputStream err; - private ExitCallback callback; - private Environment environment; - private Thread thread; + StreamHandlerAppender streamHandlerAppender; + public ConsoleReader ConsoleReader; + public SSHDCommandSender SshdCommandSender; - StreamHandlerAppender streamHandlerAppender; - public static ConsoleReader consoleReader; + public InputStream getIn() { + return in; + } - public InputStream getIn() { - return in; - } + public OutputStream getOut() { + return out; + } - public OutputStream getOut() { - return out; - } + public OutputStream getErr() { + return err; + } - public OutputStream getErr() { - return err; - } + public Environment getEnvironment() { + return environment; + } - public Environment getEnvironment() { - return environment; - } + public void setInputStream(InputStream in) { + this.in = in; + } - public void setInputStream(InputStream in) { - this.in = in; - } + public void setOutputStream(OutputStream out) { + this.out = out; + } - public void setOutputStream(OutputStream out) { - this.out = out; - } + public void setErrorStream(OutputStream err) { + this.err = err; + } - public void setErrorStream(OutputStream err) { - this.err = err; - } + public void setExitCallback(ExitCallback callback) { + this.callback = callback; + } - public void setExitCallback(ExitCallback callback) { - this.callback = callback; - } - - @Override + @Override public void start(ChannelSession cs, Environment env) throws IOException - { - try - { - consoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal()); - consoleReader.setExpandEvents(true); - consoleReader.addCompleter(new ConsoleCommandCompleter()); + { + try + { + this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal()); + this.ConsoleReader.setExpandEvents(true); + this.ConsoleReader.addCompleter(new ConsoleCommandCompleter()); - StreamHandler streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), consoleReader); - streamHandlerAppender = new StreamHandlerAppender(streamHandler); + StreamHandler streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader); + streamHandlerAppender = new StreamHandlerAppender(streamHandler); - ((Logger)LogManager.getRootLogger()).addAppender(streamHandlerAppender); + ((Logger)LogManager.getRootLogger()).addAppender(streamHandlerAppender); - environment = env; - thread = new Thread(this, "SSHD ConsoleShell " + env.getEnv().get(Environment.ENV_USER)); - thread.start(); - } - catch (Exception e) - { - throw new IOException("Error starting shell", e); - } - } + this.environment = env; + this.Username = env.getEnv().get(Environment.ENV_USER); + this.SshdCommandSender = new SSHDCommandSender(); + this.SshdCommandSender.console = this; + thread = new Thread(this, "SSHD ConsoleShell " + this.Username); + thread.start(); + } + catch (Exception e) + { + throw new IOException("Error starting shell", e); + } + } - @Override + @Override public void destroy(ChannelSession cs) { ((Logger)LogManager.getRootLogger()).removeAppender(streamHandlerAppender); } public void run() - { - try - { - if (!SshdPlugin.instance.getConfig().getString("mode").equals("RPC")) - printPreamble(consoleReader); - while (true) - { - String command = consoleReader.readLine("\r>", null); - if (command == null) - continue; - if (command.equals("exit") || command.equals("quit")) - break; - Bukkit.getScheduler().runTask( - SshdPlugin.instance, () -> - { - if (SshdPlugin.instance.getConfig().getString("mode").equals("RPC") && command.startsWith("rpc")) - { - // NO ECHO NO PREAMBLE AND SHIT - String cmd = command.substring("rpc".length() + 1, command.length()); - Bukkit.dispatchCommand(sshdCommandSender, cmd); - } - else - { - SshdPlugin.instance.getLogger().info("<" + environment.getEnv().get(Environment.ENV_USER) + "> " - + command); - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); - } - }); - } - } - catch (IOException e) - { - SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error processing command from SSH", e); - } - finally - { - callback.onExit(0); - } - } + { + try + { + if (!SshdPlugin.instance.getConfig().getString("Mode").equals("RPC")) + printPreamble(this.ConsoleReader); + while (true) + { + String command = this.ConsoleReader.readLine("\r>", null); + if (command == null || command.trim().isEmpty()) + continue; + if (command.equals("exit") || command.equals("quit")) + break; - private void printPreamble(ConsoleReader consoleReader) throws IOException - { - consoleReader.println(" _____ _____ _ _ _____" + "\r"); - consoleReader.println(" / ____/ ____| | | | __ \\" + "\r"); - consoleReader.println("| (___| (___ | |__| | | | |" + "\r"); - consoleReader.println(" \\___ \\\\___ \\| __ | | | |" + "\r"); - consoleReader.println(" ____) |___) | | | | |__| |" + "\r"); - consoleReader.println("|_____/_____/|_| |_|_____/" + "\r"); - consoleReader.println("Connected to: " + Bukkit.getServer().getName() + "\r"); - consoleReader.println("- " + Bukkit.getServer().getMotd() + "\r"); - consoleReader.println("\r"); - consoleReader.println("Type 'exit' to exit the shell." + "\r"); - consoleReader.println("===============================================" + "\r"); - } + Bukkit.getScheduler().runTask( + SshdPlugin.instance, () -> + { + if (SshdPlugin.instance.getConfig().getString("Mode").equals("RPC") && command.startsWith("rpc")) + { + // NO ECHO NO PREAMBLE AND SHIT + String cmd = command.substring("rpc".length() + 1, command.length()); + Bukkit.dispatchCommand(this.SshdCommandSender, cmd); + } + else + { + SshdPlugin.instance.getLogger().info("<" + this.Username + "> " + command); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } + }); + } + } + catch (IOException e) + { + SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error processing command from SSH", e); + } + finally + { + callback.onExit(0); + } + } + + private void printPreamble(ConsoleReader cr) throws IOException + { + cr.println(" _____ _____ _ _ _____" + "\r"); + cr.println(" / ____/ ____| | | | __ \\" + "\r"); + cr.println("| (___| (___ | |__| | | | |" + "\r"); + cr.println(" \\___ \\\\___ \\| __ | | | |" + "\r"); + cr.println(" ____) |___) | | | | |__| |" + "\r"); + cr.println("|_____/_____/|_| |_|_____/" + "\r"); + cr.println("Connected to: " + Bukkit.getServer().getName() + "\r"); + cr.println("- " + Bukkit.getServer().getMotd() + "\r"); + cr.println("\r"); + cr.println("Type 'exit' to exit the shell." + "\r"); + cr.println("===============================================" + "\r"); + } } } \ 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 b9f4ee3..0a14696 100644 --- a/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java +++ b/src/main/java/com/ryanmichela/sshd/PublicKeyAuthenticator.java @@ -8,6 +8,8 @@ import org.apache.sshd.server.session.ServerSession; import java.io.File; import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.io.FileReader; import java.security.PublicKey; @@ -16,57 +18,54 @@ import java.security.PublicKey; */ public class PublicKeyAuthenticator implements PublickeyAuthenticator { + private File authorizedKeysDir; + private Map FailCounts = new HashMap(); - private File authorizedKeysDir; - - public PublicKeyAuthenticator(File authorizedKeysDir) { this.authorizedKeysDir = authorizedKeysDir; } + 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); + File keyFile = new File(authorizedKeysDir, username); + Integer tries = SshdPlugin.instance.getConfig().getInt("LoginRetries"); if (keyFile.exists()) { try { + // Read all the public key entries List pklist = AuthorizedKeyEntry.readAuthorizedKeys(keyFile.toPath()); - + // Get an authenticator PublickeyAuthenticator auth = PublickeyAuthenticator.fromAuthorizedEntries(username, session, pklist, PublicKeyEntryResolver.IGNORING); - boolean accepted = auth.authenticate(username, key, session); - - if (accepted) - { + // Validate that the logging in user has the same valid SSH key + if (auth.authenticate(username, key, session)) + { SshdPlugin.instance.getLogger().info( username + " successfully authenticated via SSH session using key file " + keyFile.getAbsolutePath()); + FailCounts.put(username, 0); + return true; } else { SshdPlugin.instance.getLogger().info( username + " failed authentication via SSH session using key file " + keyFile.getAbsolutePath()); } - return accepted; - /* - FileReader fr = new FileReader(keyFile); - PemDecoder pd = new PemDecoder(fr); - PublicKey k = pd.getPemBytes(); - pd.close(); - - if (k != null) - { - if (ArrayUtils.isEquals(key.getEncoded(), k.getEncoded())) - { - return true; - } - } + // If the user fails with several SSH keys, then terminate the connection. + if (this.FailCounts.containsKey(username)) + this.FailCounts.put(username, this.FailCounts.get(username) + 1); else + this.FailCounts.put(username, 1); + + if (this.FailCounts.get(username) >= tries) { - SshdPlugin.instance.getLogger().severe("Failed to parse PEM file. " + keyFile.getAbsolutePath()); - } - */ + this.FailCounts.put(username, 0); + session.close(true); + } + + return false; } catch (Exception e) { diff --git a/src/main/java/com/ryanmichela/sshd/SshdPlugin.java b/src/main/java/com/ryanmichela/sshd/SshdPlugin.java index 79d84e4..01e48c2 100644 --- a/src/main/java/com/ryanmichela/sshd/SshdPlugin.java +++ b/src/main/java/com/ryanmichela/sshd/SshdPlugin.java @@ -44,8 +44,8 @@ class SshdPlugin extends JavaPlugin instance = this; sshd = SshServer.setUpDefaultServer(); - sshd.setPort(getConfig().getInt("port", 22)); - String host = getConfig().getString("listenAddress", "all"); + sshd.setPort(getConfig().getInt("Port", 1025)); + String host = getConfig().getString("ListenAddress", "all"); sshd.setHost(host.equals("all") ? null : host); File hostKey = new File(getDataFolder(), "hostkey"); @@ -56,7 +56,7 @@ class SshdPlugin extends JavaPlugin sshd.setPasswordAuthenticator(new ConfigPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new PublicKeyAuthenticator(authorizedKeys)); - if (getConfig().getBoolean("enableSFTP")) + if (getConfig().getBoolean("EnableSFTP")) { sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory())); sshd.setFileSystemFactory( diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java index 5442e00..30b7baf 100644 --- a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java @@ -24,108 +24,116 @@ import java.util.logging.Level; public class SSHDCommandSender implements ConsoleCommandSender, CommandSender { - private final PermissibleBase perm = new PermissibleBase(this); - private final SSHDConversationTracker conversationTracker = new SSHDConversationTracker(); + private final PermissibleBase perm = new PermissibleBase(this); + private final SSHDConversationTracker conversationTracker = new SSHDConversationTracker(); + // Set by the upstream allocating function + public ConsoleShellFactory.ConsoleShell console; - public void sendMessage(String message) { - this.sendRawMessage(message); - } + public void sendMessage(String message) { + this.sendRawMessage(message); + } - public void sendRawMessage(String message) { - if(ConsoleShellFactory.ConsoleShell.consoleReader == null) return; - try { - ConsoleShellFactory.ConsoleShell.consoleReader.println(ChatColor.stripColor(message)); - } catch (IOException e) { - SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error sending message to SSHDCommandSender", e); - } - } + public void sendRawMessage(String message) + { + // What the fuck does this code even do? Are we sending to one client or all of them? + if (this.console.ConsoleReader == null) + return; + try + { + this.console.ConsoleReader.println(ChatColor.stripColor(message)); + } + catch (IOException e) + { + SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error sending message to SSHDCommandSender", e); + } + } - public void sendMessage(String[] messages) { - Arrays.asList(messages).forEach(this::sendMessage); - } + public void sendMessage(String[] messages) { + Arrays.asList(messages).forEach(this::sendMessage); + } - public String getName() { - return "Console"; - } + public String getName() { + return "SSHD Console"; + } - public boolean isOp() { - return true; - } + public boolean isOp() { + return true; + } - public void setOp(boolean value) { - throw new UnsupportedOperationException("Cannot change operator status of server console"); - } + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of server console"); + } - public boolean beginConversation(Conversation conversation) { - return this.conversationTracker.beginConversation(conversation); - } + public boolean beginConversation(Conversation conversation) { + return this.conversationTracker.beginConversation(conversation); + } - public void abandonConversation(Conversation conversation) { - this.conversationTracker.abandonConversation(conversation, new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); - } + public void abandonConversation(Conversation conversation) { + this.conversationTracker.abandonConversation(conversation, new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); + } - public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { - this.conversationTracker.abandonConversation(conversation, details); - } + public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { + this.conversationTracker.abandonConversation(conversation, details); + } - public void acceptConversationInput(String input) { - this.conversationTracker.acceptConversationInput(input); - } + public void acceptConversationInput(String input) { + this.conversationTracker.acceptConversationInput(input); + } - public boolean isConversing() { - return this.conversationTracker.isConversing(); - } + public boolean isConversing() { + return this.conversationTracker.isConversing(); + } - public boolean isPermissionSet(String name) { - return this.perm.isPermissionSet(name); - } + public boolean isPermissionSet(String name) { + return this.perm.isPermissionSet(name); + } - public boolean isPermissionSet(Permission perm) { - return this.perm.isPermissionSet(perm); - } + public boolean isPermissionSet(Permission perm) { + return this.perm.isPermissionSet(perm); + } - public boolean hasPermission(String name) { - return this.perm.hasPermission(name); - } + public boolean hasPermission(String name) { + return this.perm.hasPermission(name); + } - public boolean hasPermission(Permission perm) { - return this.perm.hasPermission(perm); - } + public boolean hasPermission(Permission perm) { + return this.perm.hasPermission(perm); + } - public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { - return this.perm.addAttachment(plugin, name, value); - } + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { + return this.perm.addAttachment(plugin, name, value); + } - public PermissionAttachment addAttachment(Plugin plugin) { - return this.perm.addAttachment(plugin); - } + public PermissionAttachment addAttachment(Plugin plugin) { + return this.perm.addAttachment(plugin); + } - public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { - return this.perm.addAttachment(plugin, name, value, ticks); - } + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { + return this.perm.addAttachment(plugin, name, value, ticks); + } - public PermissionAttachment addAttachment(Plugin plugin, int ticks) { - return this.perm.addAttachment(plugin, ticks); - } + public PermissionAttachment addAttachment(Plugin plugin, int ticks) { + return this.perm.addAttachment(plugin, ticks); + } - public void removeAttachment(PermissionAttachment attachment) { - this.perm.removeAttachment(attachment); - } + public void removeAttachment(PermissionAttachment attachment) { + this.perm.removeAttachment(attachment); + } - public void recalculatePermissions() { - this.perm.recalculatePermissions(); - } + public void recalculatePermissions() { + this.perm.recalculatePermissions(); + } - public Set getEffectivePermissions() { - return this.perm.getEffectivePermissions(); - } + public Set getEffectivePermissions() { + return this.perm.getEffectivePermissions(); + } - public boolean isPlayer() { - return false; - } + public boolean isPlayer() { + return false; + } - public Server getServer() { - return Bukkit.getServer(); - } + public Server getServer() { + return Bukkit.getServer(); + } } diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java index 947ef2d..5b9bb4f 100644 --- a/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java @@ -9,70 +9,70 @@ import java.util.LinkedList; import java.util.logging.Level; public class SSHDConversationTracker { - private LinkedList conversationQueue = new LinkedList<>(); + private LinkedList conversationQueue = new LinkedList<>(); - synchronized boolean beginConversation(Conversation conversation) { - if (!this.conversationQueue.contains(conversation)) { - this.conversationQueue.addLast(conversation); - if (this.conversationQueue.getFirst() == conversation) { - conversation.begin(); - conversation.outputNextPrompt(); - return true; - } - } + synchronized boolean beginConversation(Conversation conversation) { + if (!this.conversationQueue.contains(conversation)) { + this.conversationQueue.addLast(conversation); + if (this.conversationQueue.getFirst() == conversation) { + conversation.begin(); + conversation.outputNextPrompt(); + return true; + } + } - return true; - } + return true; + } - synchronized void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { - if (!this.conversationQueue.isEmpty()) { - if (this.conversationQueue.getFirst() == conversation) { - conversation.abandon(details); - } + synchronized void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { + if (!this.conversationQueue.isEmpty()) { + if (this.conversationQueue.getFirst() == conversation) { + conversation.abandon(details); + } - if (this.conversationQueue.contains(conversation)) { - this.conversationQueue.remove(conversation); - } + if (this.conversationQueue.contains(conversation)) { + this.conversationQueue.remove(conversation); + } - if (!this.conversationQueue.isEmpty()) { - this.conversationQueue.getFirst().outputNextPrompt(); - } - } + if (!this.conversationQueue.isEmpty()) { + this.conversationQueue.getFirst().outputNextPrompt(); + } + } - } + } - public synchronized void abandonAllConversations() { - LinkedList oldQueue = this.conversationQueue; - this.conversationQueue = new LinkedList<>(); + public synchronized void abandonAllConversations() { + LinkedList oldQueue = this.conversationQueue; + this.conversationQueue = new LinkedList<>(); - for (Conversation conversation : oldQueue) { - try { - conversation.abandon(new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); - } catch (Throwable var5) { - Bukkit.getLogger().log(Level.SEVERE, "Unexpected exception while abandoning a conversation", var5); - } - } + for (Conversation conversation : oldQueue) { + try { + conversation.abandon(new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); + } catch (Throwable var5) { + Bukkit.getLogger().log(Level.SEVERE, "Unexpected exception while abandoning a conversation", var5); + } + } - } + } - synchronized void acceptConversationInput(String input) { - if (this.isConversing()) { - Conversation conversation = this.conversationQueue.getFirst(); + synchronized void acceptConversationInput(String input) { + if (this.isConversing()) { + Conversation conversation = this.conversationQueue.getFirst(); - try { - conversation.acceptInput(input); - } catch (Throwable var4) { - conversation.getContext().getPlugin().getLogger().log(Level.WARNING, String.format("Plugin %s generated an exception whilst handling conversation input", conversation.getContext().getPlugin().getDescription().getFullName()), var4); - } - } + try { + conversation.acceptInput(input); + } catch (Throwable var4) { + conversation.getContext().getPlugin().getLogger().log(Level.WARNING, String.format("Plugin %s generated an exception whilst handling conversation input", conversation.getContext().getPlugin().getDescription().getFullName()), var4); + } + } - } + } - synchronized boolean isConversing() { - return !this.conversationQueue.isEmpty(); - } + synchronized boolean isConversing() { + return !this.conversationQueue.isEmpty(); + } - public synchronized boolean isConversingModaly() { - return this.isConversing() && this.conversationQueue.getFirst().isModal(); - } + public synchronized boolean isConversingModaly() { + return this.isConversing() && this.conversationQueue.getFirst().isModal(); + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5427555..31e049c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,22 +1,35 @@ # The IP addresses(s) the SSH server will listen on. Use a comma separated list for multiple addresses. # Leave as "all" for all addresses. -listenAddress: all -# The port the SSH server will listen on. -port: 22 +ListenAddress: all +# The port the SSH server will listen on. Note that anything above 1024 will require you to run +# the whole minecraft server with elevated privileges, this is not recommended and you should +# use iptables to route packets from a lower port. +Port: 1025 # Operational mode. Don't touch if you don't know what you're doing. Can be either DEFAULT or RPC -mode: DEFAULT +Mode: DEFAULT # Enable built-in SFTP server or not. You'll be able to connect and upload/download files via SFTP protocol. # Might be useful for testing purposes as well , i. e. docker containers. -enableSFTP: true +EnableSFTP: true + +# Number of times a person can fail to use an SSH key or enter a password +# before it terminates the connection. +LoginRetries: 3 # By default, only public key authentication is enabled. This is the most secure mode. -# To authorize a user to log in with public key authentication, install their public -# PEM certificate in the authorized_users directory. Name the key file with user's user -# name (no file extension). +# To authorize a user to login with their public key, install their key using the +# OpenSSH authorized_keys file format in the authorized_users directory. Name the key +# file with the user's username and no extension. Note: If you want to let a user have +# many keys, you can append the keys to their file in authorized_users. # For less secure username and password based authentication, complete the sections below. -credentials: + +# Type of hashing to use for the passwords below. +# Options are: PLAIN (insecure), bcrypt, pbkdf, sha256 +PasswordType: bcrypt + +# Associate each username with a password hash (or the password if the PasswordType is set to PLAIN) +Credentials: # user1: password1 # user2: password2