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:
parent
b51a03e2d5
commit
33f34ad54d
@ -3,49 +3,63 @@ package com.ryanmichela.sshd;
|
||||
/**
|
||||
* Copyright 2013 Ryan Michela
|
||||
*/
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import jline.console.completer.Completer;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
// 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<CharSequence> candidates) {
|
||||
Waitable<List<String>> waitable = new Waitable<List<String>>() {
|
||||
public class ConsoleCommandCompleter implements Completer
|
||||
{
|
||||
public int complete(final String buffer, final int cursor, final List<CharSequence> candidates)
|
||||
{
|
||||
Waitable<List<String>> waitable = new Waitable<List<String>>()
|
||||
{
|
||||
@Override
|
||||
protected List<String> evaluate() {
|
||||
CommandMap commandMap = ReflectionUtil.getProtectedValue(Bukkit.getServer(), "commandMap");
|
||||
return commandMap.tabComplete(Bukkit.getServer().getConsoleSender(), buffer);
|
||||
protected List<String> evaluate()
|
||||
{
|
||||
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);
|
||||
try {
|
||||
try
|
||||
{
|
||||
List<String> offers = waitable.get();
|
||||
if (offers == null) {
|
||||
if (offers == null)
|
||||
return cursor;
|
||||
}
|
||||
|
||||
candidates.addAll(offers);
|
||||
|
||||
final int lastSpace = buffer.lastIndexOf(' ');
|
||||
if (lastSpace == -1) {
|
||||
if (lastSpace == -1)
|
||||
return cursor - buffer.length();
|
||||
} else {
|
||||
else
|
||||
return cursor - (buffer.length() - lastSpace - 1);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
SshdPlugin.instance.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import com.ryanmichela.sshd.FlushyOutputStream;
|
||||
import com.ryanmichela.sshd.FlushyStreamHandler;
|
||||
import com.ryanmichela.sshd.SshTerminal;
|
||||
import com.ryanmichela.sshd.SshdPlugin;
|
||||
import com.ryanmichela.sshd.StreamHandlerAppender;
|
||||
import com.ryanmichela.sshd.implementations.SSHDCommandSender;
|
||||
import com.ryanmichela.sshd.ConsoleLogFormatter;
|
||||
import jline.console.ConsoleReader;
|
||||
@ -52,7 +51,6 @@ public class ConsoleShellFactory implements ShellFactory {
|
||||
private Thread thread;
|
||||
private String Username;
|
||||
|
||||
StreamHandlerAppender streamHandlerAppender;
|
||||
StreamHandler streamHandler;
|
||||
public ConsoleReader ConsoleReader;
|
||||
public SSHDCommandSender SshdCommandSender;
|
||||
@ -96,10 +94,9 @@ 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 = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader);
|
||||
this.streamHandlerAppender = new StreamHandlerAppender(streamHandler);
|
||||
|
||||
SshdPlugin.instance.getProxy().getLogger().addHandler(this.streamHandler);
|
||||
|
||||
|
@ -36,10 +36,12 @@ public class MkpasswdCommand extends Command
|
||||
// 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));
|
||||
if (password.length() == 0)
|
||||
throw new ArrayIndexOutOfBoundsException(); // shortcut
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
// ignore it.
|
||||
this.SendSyntax(sender, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -81,92 +83,3 @@ 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;
|
||||
}
|
||||
}*/
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user