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