Get this to a release state

- Fixed CommandCompleter so tab completion works again.
- Fixed most of the mkpasswd command, it's also now more secure as it
only shows in your SSH session and not other's consoles.
- Removed some now unused code.
This commit is contained in:
Zachery 2019-10-10 01:12:38 -05:00
parent b51a03e2d5
commit 33f34ad54d
No known key found for this signature in database
GPG Key ID: 0C6201265CE80EEE
5 changed files with 41 additions and 305 deletions

View File

@ -3,49 +3,63 @@ package com.ryanmichela.sshd;
/** /**
* Copyright 2013 Ryan Michela * Copyright 2013 Ryan Michela
*/ */
import net.md_5.bungee.api.plugin.Command;
import jline.console.completer.Completer; import jline.console.completer.Completer;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.logging.Level; 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 int complete(final String buffer, final int cursor, final List<CharSequence> candidates)
public class ConsoleCommandCompleter /*implements Completer*/ { {
Waitable<List<String>> waitable = new Waitable<List<String>>()
/* {
public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
Waitable<List<String>> waitable = new Waitable<List<String>>() {
@Override @Override
protected List<String> evaluate() { protected List<String> evaluate()
CommandMap commandMap = ReflectionUtil.getProtectedValue(Bukkit.getServer(), "commandMap"); {
return commandMap.tabComplete(Bukkit.getServer().getConsoleSender(), buffer); List<String> tabcomplete = new ArrayList<String>();
for (Map.Entry<String, Command> map : SshdPlugin.instance.getProxy().getPluginManager().getCommands())
{
String cmd = map.getKey();
Command value = map.getValue();
if (cmd.startsWith(buffer))
tabcomplete.add(cmd);
}
return tabcomplete;
} }
}; };
SshdPlugin.instance.getProxy().getScheduler().runAsync(SshdPlugin.instance, waitable); SshdPlugin.instance.getProxy().getScheduler().runAsync(SshdPlugin.instance, waitable);
try { try
{
List<String> offers = waitable.get(); List<String> offers = waitable.get();
if (offers == null) { if (offers == null)
return cursor; return cursor;
}
candidates.addAll(offers); candidates.addAll(offers);
final int lastSpace = buffer.lastIndexOf(' '); final int lastSpace = buffer.lastIndexOf(' ');
if (lastSpace == -1) { if (lastSpace == -1)
return cursor - buffer.length(); return cursor - buffer.length();
} else { else
return cursor - (buffer.length() - lastSpace - 1); return cursor - (buffer.length() - lastSpace - 1);
} }
} catch (ExecutionException e) { catch (ExecutionException e)
{
SshdPlugin.instance.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); SshdPlugin.instance.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
} catch (InterruptedException e) { }
catch (InterruptedException e)
{
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
return cursor; return cursor;
} }
*/
} }

View File

@ -6,7 +6,6 @@ import com.ryanmichela.sshd.FlushyOutputStream;
import com.ryanmichela.sshd.FlushyStreamHandler; import com.ryanmichela.sshd.FlushyStreamHandler;
import com.ryanmichela.sshd.SshTerminal; import com.ryanmichela.sshd.SshTerminal;
import com.ryanmichela.sshd.SshdPlugin; import com.ryanmichela.sshd.SshdPlugin;
import com.ryanmichela.sshd.StreamHandlerAppender;
import com.ryanmichela.sshd.implementations.SSHDCommandSender; import com.ryanmichela.sshd.implementations.SSHDCommandSender;
import com.ryanmichela.sshd.ConsoleLogFormatter; import com.ryanmichela.sshd.ConsoleLogFormatter;
import jline.console.ConsoleReader; import jline.console.ConsoleReader;
@ -52,7 +51,6 @@ public class ConsoleShellFactory implements ShellFactory {
private Thread thread; private Thread thread;
private String Username; private String Username;
StreamHandlerAppender streamHandlerAppender;
StreamHandler streamHandler; StreamHandler streamHandler;
public ConsoleReader ConsoleReader; public ConsoleReader ConsoleReader;
public SSHDCommandSender SshdCommandSender; public SSHDCommandSender SshdCommandSender;
@ -96,10 +94,9 @@ public class ConsoleShellFactory implements ShellFactory {
{ {
this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal()); this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal());
this.ConsoleReader.setExpandEvents(true); this.ConsoleReader.setExpandEvents(true);
//this.ConsoleReader.addCompleter(new ConsoleCommandCompleter()); this.ConsoleReader.addCompleter(new ConsoleCommandCompleter());
streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader); streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader);
this.streamHandlerAppender = new StreamHandlerAppender(streamHandler);
SshdPlugin.instance.getProxy().getLogger().addHandler(this.streamHandler); SshdPlugin.instance.getProxy().getLogger().addHandler(this.streamHandler);

View File

@ -36,10 +36,12 @@ public class MkpasswdCommand extends Command
// spaces in their passwords otherwise it won't be as strong as it should be. // spaces in their passwords otherwise it won't be as strong as it should be.
algoritm = args[0]; algoritm = args[0];
password = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); password = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
if (password.length() == 0)
throw new ArrayIndexOutOfBoundsException(); // shortcut
} }
catch (ArrayIndexOutOfBoundsException e) catch (ArrayIndexOutOfBoundsException e)
{ {
// ignore it. this.SendSyntax(sender, false);
return; return;
} }
@ -48,7 +50,7 @@ public class MkpasswdCommand extends Command
boolean hasperm = (sender instanceof ProxiedPlayer) ? ((ProxiedPlayer)sender).hasPermission("sshd.mkpasswd") : true; boolean hasperm = (sender instanceof ProxiedPlayer) ? ((ProxiedPlayer)sender).hasPermission("sshd.mkpasswd") : true;
if (hasperm) if (hasperm)
{ {
try try
{ {
String hash = ""; String hash = "";
@ -80,93 +82,4 @@ public class MkpasswdCommand extends Command
} }
} }
} }
} }
/*
class MkpasswdCommand implements CommandExecutor
{
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
{
String algoritm, password;
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.
algoritm = args[0];
password = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
}
catch (ArrayIndexOutOfBoundsException e)
{
// ignore it.
return false;
}
// If they're console, allow regardless.
if (!(sender instanceof Player))
{
if (label.equalsIgnoreCase("mkpasswd"))
{
try
{
// Dumb but whatever. Some people are really dense.
if (algoritm.equalsIgnoreCase("PLAIN"))
{
// I mean c'mon...
sender.sendMessage("Bro really? it's literally your unencrypted password...");
}
else if (algoritm.equalsIgnoreCase("pbkdf2"))
sender.sendMessage("Your hash: " + Cryptography.PBKDF2_HashPassword(password));
else if (algoritm.equalsIgnoreCase("bcrypt"))
sender.sendMessage("Your hash: " + Cryptography.BCrypt_HashPassword(password));
else if (algoritm.equalsIgnoreCase("sha256"))
sender.sendMessage("Your hash: " + Cryptography.SHA256_HashPassword(password));
else if (algoritm.equalsIgnoreCase("help"))
sender.sendMessage("Supported hash algorithms: pbkdf2, bcrypt, sha256, plain");
else
return false;
}
catch (Exception e)
{
// We're console, just print the stack trace.
e.printStackTrace();
return false;
}
return true;
}
}
else
{
Player player = (Player) sender;
if (label.equalsIgnoreCase("mkpasswd"))
{
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));
else
return false;
}
}
catch (Exception e)
{
// since this is a player, send a failure message
sender.sendMessage("An error occured, please check console.");
e.printStackTrace();
return false;
}
return true;
}
}
return false;
}
}*/

View File

@ -1,96 +0,0 @@
package com.ryanmichela.sshd;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Copyright 2013 Ryan Michela
*/
public class ReflectionUtil {
public static void setProtectedValue(Object o, String field, Object newValue) {
setProtectedValue(o.getClass(), o, field, newValue);
}
public static void setProtectedValue(Class c, String field, Object newValue) {
setProtectedValue(c, null, field, newValue);
}
public static void setProtectedValue(Class c, Object o, String field, Object newValue) {
try {
Field f = c.getDeclaredField(field);
f.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(o, newValue);
} catch (NoSuchFieldException | IllegalAccessException ex) {
System.out.println("*** " + c.getName() + ":" + ex);
}
}
public static <T> T getProtectedValue(Object obj, String fieldName) {
try {
Class c = obj.getClass();
while (c != Object.class) {
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
if (f.getName() == fieldName) {
f.setAccessible(true);
return (T) f.get(obj);
}
}
c = c.getSuperclass();
}
System.out.println("*** " + obj.getClass().getName() + ":No such field");
return null;
} catch (Exception ex) {
System.out.println("*** " + obj.getClass().getName() + ":" + ex);
return null;
}
}
public static <T> T getProtectedValue(Class c, String field) {
try {
Field f = c.getDeclaredField(field);
f.setAccessible(true);
return (T) f.get(c);
} catch (Exception ex) {
System.out.println("*** " + c.getName() + ":" + ex);
return null;
}
}
public static Object invokeProtectedMethod(Class c, String method, Object... args) {
return invokeProtectedMethod(c, null, method, args);
}
public static Object invokeProtectedMethod(Object o, String method, Object... args) {
return invokeProtectedMethod(o.getClass(), o, method, args);
}
public static Object invokeProtectedMethod(Class c, Object o, String method, Object... args) {
try {
Class[] pTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Integer) {
pTypes[i] = int.class;
} else {
pTypes[i] = args[i].getClass();
}
}
Method m = c.getDeclaredMethod(method, pTypes);
m.setAccessible(true);
return m.invoke(o, args);
} catch (Exception ex) {
System.out.println("*** " + c.getName() + "." + method + "(): " + ex);
return null;
}
}
}

View File

@ -1,92 +0,0 @@
package com.ryanmichela.sshd;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.ErrorHandler;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import java.io.Serializable;
import java.util.UUID;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
/**
* Copyright 2014 Ryan Michela
*/
public class StreamHandlerAppender implements Appender {
private StreamHandler streamHandler;
private UUID uuid;
public StreamHandlerAppender(StreamHandler streamHandler) {
this.streamHandler = streamHandler;
uuid = UUID.randomUUID();
}
@Override
public void append(LogEvent logEvent) {
java.util.logging.Level level;
if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.DEBUG)) {
level = java.util.logging.Level.FINE;
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.INFO)) {
level = java.util.logging.Level.INFO;
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.WARN)) {
level = java.util.logging.Level.WARNING;
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.ERROR)) {
level = java.util.logging.Level.SEVERE;
} else {
level = java.util.logging.Level.INFO;
}
String message = logEvent.getMessage().getFormattedMessage();
LogRecord logRecord = new LogRecord(level, message);
streamHandler.publish(logRecord);
}
@Override
public String getName() {
return "StreamHandlerAppender:" + uuid.toString();
}
@Override
public Layout<? extends Serializable> getLayout() {
return null;
}
@Override
public boolean ignoreExceptions() {
return false;
}
@Override
public ErrorHandler getHandler() {
return null;
}
@Override
public void setHandler(ErrorHandler errorHandler) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public boolean isStarted() {
return true;
}
@Override
public boolean isStopped() {
return false;
}
}