Initial commit.
This commit is contained in:
parent
101b7eb972
commit
e98113397d
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,3 +4,6 @@
|
|||||||
*.jar
|
*.jar
|
||||||
*.war
|
*.war
|
||||||
*.ear
|
*.ear
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
target
|
||||||
|
95
pom.xml
Normal file
95
pom.xml
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.ryanmichela</groupId>
|
||||||
|
<artifactId>SSHD</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<url>http://dev.bukkit.org/server-mods/sshd/</url>
|
||||||
|
|
||||||
|
<!-- Repositories -->
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>bukkit-repo</id>
|
||||||
|
<url>http://repo.bukkit.org/content/groups/public/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<!-- License -->
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>GPL2</name>
|
||||||
|
<url>http://www.gnu.org/licenses/gpl-2.0.html</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<!-- Dependencies -->
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>craftbukkit</artifactId>
|
||||||
|
<version>1.6.4-R1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<type>jar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sshd</groupId>
|
||||||
|
<artifactId>sshd-core</artifactId>
|
||||||
|
<version>0.9.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<type>jar</type>
|
||||||
|
</dependency>
|
||||||
|
<!--<dependency>-->
|
||||||
|
<!--<groupId>org.bouncycastle</groupId>-->
|
||||||
|
<!--<artifactId>bcprov-jdk16</artifactId>-->
|
||||||
|
<!--<version>1.46</version>-->
|
||||||
|
<!--</dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<!-- Build -->
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Shade plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- Compile plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.7</source>
|
||||||
|
<target>1.7</target>
|
||||||
|
<showDeprecation>true</showDeprecation>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
</project>
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.server.PasswordAuthenticator;
|
||||||
|
import org.apache.sshd.server.session.ServerSession;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class ConfigPasswordAuthenticator implements PasswordAuthenticator {
|
||||||
|
private Map<String, Integer> failCounts = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
@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.");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
|
import org.bukkit.craftbukkit.libs.jline.console.completer.Completer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Bukkit.getScheduler().runTask(SshdPlugin.instance, waitable);
|
||||||
|
try {
|
||||||
|
List<String> offers = waitable.get();
|
||||||
|
if (offers == null) {
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
candidates.addAll(offers);
|
||||||
|
|
||||||
|
final int lastSpace = buffer.lastIndexOf(' ');
|
||||||
|
if (lastSpace == -1) {
|
||||||
|
return cursor - buffer.length();
|
||||||
|
} else {
|
||||||
|
return cursor - (buffer.length() - lastSpace - 1);
|
||||||
|
}
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
SshdPlugin.instance.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.server.Command;
|
||||||
|
import org.apache.sshd.server.CommandFactory;
|
||||||
|
import org.apache.sshd.server.Environment;
|
||||||
|
import org.apache.sshd.server.ExitCallback;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class ConsoleCommandFactory implements CommandFactory {
|
||||||
|
@Override
|
||||||
|
public Command createCommand(String command) {
|
||||||
|
return new ConsoleCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConsoleCommand implements Command {
|
||||||
|
private String command;
|
||||||
|
|
||||||
|
private InputStream in;
|
||||||
|
private OutputStream out;
|
||||||
|
private OutputStream err;
|
||||||
|
private ExitCallback callback;
|
||||||
|
|
||||||
|
public ConsoleCommand(String command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputStream(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorStream(OutputStream err) {
|
||||||
|
this.err = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExitCallback(ExitCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Environment environment) throws IOException {
|
||||||
|
try {
|
||||||
|
SshdPlugin.instance.getLogger().info("[U: " + environment.getEnv().get(Environment.ENV_USER) + "] " + command);
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||||
|
} catch (Exception e) {
|
||||||
|
SshdPlugin.instance.getLogger().severe("Error processing command from SSH");
|
||||||
|
} finally {
|
||||||
|
callback.onExit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
128
src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java
Normal file
128
src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.common.Factory;
|
||||||
|
import org.apache.sshd.server.Command;
|
||||||
|
import org.apache.sshd.server.Environment;
|
||||||
|
import org.apache.sshd.server.ExitCallback;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.craftbukkit.libs.jline.console.ConsoleReader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.logging.StreamHandler;
|
||||||
|
|
||||||
|
public class ConsoleShellFactory implements Factory<Command> {
|
||||||
|
|
||||||
|
public Command create() {
|
||||||
|
return new ConsoleShell();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
StreamHandler streamHandler;
|
||||||
|
ConsoleReader consoleReader;
|
||||||
|
|
||||||
|
public InputStream getIn() {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getOut() {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getErr() {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Environment getEnvironment() {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputStream(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorStream(OutputStream err) {
|
||||||
|
this.err = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExitCallback(ExitCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(Environment env) throws IOException {
|
||||||
|
|
||||||
|
Formatter bukkitFormatter = Bukkit.getLogger().getHandlers()[0].getFormatter();
|
||||||
|
|
||||||
|
try {
|
||||||
|
consoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal());
|
||||||
|
consoleReader.setExpandEvents(true);
|
||||||
|
consoleReader.addCompleter(new ConsoleCommandCompleter());
|
||||||
|
|
||||||
|
streamHandler = new FlushyStreamHandler(out, bukkitFormatter, consoleReader);
|
||||||
|
Bukkit.getLogger().addHandler(streamHandler);
|
||||||
|
Logger.getLogger("").addHandler(streamHandler);
|
||||||
|
|
||||||
|
environment = env;
|
||||||
|
thread = new Thread(this, "EchoShell " + env.getEnv().get(Environment.ENV_USER));
|
||||||
|
thread.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException("Error starting shell", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
Bukkit.getLogger().removeHandler(streamHandler);
|
||||||
|
Logger.getLogger("").removeHandler(streamHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
String command;
|
||||||
|
try {
|
||||||
|
printPreamble(consoleReader);
|
||||||
|
while(true) {
|
||||||
|
command = consoleReader.readLine("\r>", null);
|
||||||
|
if (command != null) {
|
||||||
|
if (command.equals("exit")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SshdPlugin.instance.getLogger().info("[U: " + environment.getEnv().get(Environment.ENV_USER) + "] " + command);
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
SshdPlugin.instance.getLogger().severe("Error processing command from SSH");
|
||||||
|
} finally {
|
||||||
|
callback.onExit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printPreamble(ConsoleReader consoleReader) throws IOException{
|
||||||
|
consoleReader.println(" _____ _____ _ _ _____");
|
||||||
|
consoleReader.println(" / ____/ ____| | | | __ \\");
|
||||||
|
consoleReader.println("| (___| (___ | |__| | | | |");
|
||||||
|
consoleReader.println(" \\___ \\\\___ \\| __ | | | |");
|
||||||
|
consoleReader.println(" ____) |___) | | | | |__| |");
|
||||||
|
consoleReader.println("|_____/_____/|_| |_|_____/");
|
||||||
|
consoleReader.println("Connected to: " + Bukkit.getServer().getName());
|
||||||
|
consoleReader.println("- " + Bukkit.getServer().getMotd());
|
||||||
|
consoleReader.println();
|
||||||
|
consoleReader.println("Type 'exit' to exit the shell.");
|
||||||
|
consoleReader.println("===============================================");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/main/java/com/ryanmichela/sshd/FlushyOutputStream.java
Normal file
33
src/main/java/com/ryanmichela/sshd/FlushyOutputStream.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class FlushyOutputStream extends OutputStream {
|
||||||
|
private OutputStream base;
|
||||||
|
|
||||||
|
public FlushyOutputStream(OutputStream base) {
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
base.write(b);
|
||||||
|
base.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b) throws IOException {
|
||||||
|
base.write(b);
|
||||||
|
base.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int off, int len) throws IOException {
|
||||||
|
base.write(b, off, len);
|
||||||
|
base.flush();
|
||||||
|
}
|
||||||
|
}
|
48
src/main/java/com/ryanmichela/sshd/FlushyStreamHandler.java
Normal file
48
src/main/java/com/ryanmichela/sshd/FlushyStreamHandler.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.common.SshException;
|
||||||
|
import org.bukkit.craftbukkit.libs.jline.console.ConsoleReader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.logging.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class FlushyStreamHandler extends StreamHandler {
|
||||||
|
private ConsoleReader reader;
|
||||||
|
|
||||||
|
public FlushyStreamHandler(OutputStream out, Formatter formatter, ConsoleReader reader) {
|
||||||
|
super(out, formatter);
|
||||||
|
this.reader = reader;
|
||||||
|
setLevel(Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void publish(LogRecord record) {
|
||||||
|
record.setMessage(record.getMessage().replace("\n", "\n\r"));
|
||||||
|
super.publish(record);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void flush() {
|
||||||
|
try {
|
||||||
|
reader.print(ConsoleReader.RESET_LINE + "");
|
||||||
|
reader.flush();
|
||||||
|
super.flush();
|
||||||
|
try {
|
||||||
|
reader.drawLine();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
reader.getCursorBuffer().clear();
|
||||||
|
}
|
||||||
|
reader.flush();
|
||||||
|
super.flush();
|
||||||
|
} catch (SshException ex) {
|
||||||
|
// do nothing
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(FlushyStreamHandler.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
src/main/java/com/ryanmichela/sshd/PemDecoder.java
Normal file
97
src/main/java/com/ryanmichela/sshd/PemDecoder.java
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.mina.util.Base64;
|
||||||
|
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.DSAPublicKeySpec;
|
||||||
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class PemDecoder extends java.io.BufferedReader {
|
||||||
|
private static final String BEGIN = "^-+\\s*BEGIN.+";
|
||||||
|
private static final String END = "^-+\\s*END.+";
|
||||||
|
private static final String COMMENT = "Comment:";
|
||||||
|
|
||||||
|
public PemDecoder(Reader in) {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicKey getPemBytes() throws Exception {
|
||||||
|
StringBuffer b64 = new StringBuffer();
|
||||||
|
|
||||||
|
String line = readLine();
|
||||||
|
if (!line.matches(BEGIN)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(line = readLine(); line != null; line = readLine()) {
|
||||||
|
if (!line.matches(END) && !line.startsWith(COMMENT)) {
|
||||||
|
b64.append(line.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodePublicKey(b64.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] bytes;
|
||||||
|
private int pos;
|
||||||
|
|
||||||
|
private PublicKey decodePublicKey(String keyLine) throws Exception {
|
||||||
|
bytes = null;
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
|
// look for the Base64 encoded part of the line to decode
|
||||||
|
// both ssh-rsa and ssh-dss begin with "AAAA" due to the length bytes
|
||||||
|
for (String part : keyLine.split(" ")) {
|
||||||
|
if (part.startsWith("AAAA")) {
|
||||||
|
bytes = Base64.decodeBase64(part.getBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bytes == null) {
|
||||||
|
throw new IllegalArgumentException("no Base64 part to decode");
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = decodeType();
|
||||||
|
if (type.equals("ssh-rsa")) {
|
||||||
|
BigInteger e = decodeBigInt();
|
||||||
|
BigInteger m = decodeBigInt();
|
||||||
|
RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
|
||||||
|
return KeyFactory.getInstance("RSA").generatePublic(spec);
|
||||||
|
} else if (type.equals("ssh-dss")) {
|
||||||
|
BigInteger p = decodeBigInt();
|
||||||
|
BigInteger q = decodeBigInt();
|
||||||
|
BigInteger g = decodeBigInt();
|
||||||
|
BigInteger y = decodeBigInt();
|
||||||
|
DSAPublicKeySpec spec = new DSAPublicKeySpec(y, p, q, g);
|
||||||
|
return KeyFactory.getInstance("DSA").generatePublic(spec);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("unknown type " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decodeType() {
|
||||||
|
int len = decodeInt();
|
||||||
|
String type = new String(bytes, pos, len);
|
||||||
|
pos += len;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int decodeInt() {
|
||||||
|
return ((bytes[pos++] & 0xFF) << 24) | ((bytes[pos++] & 0xFF) << 16)
|
||||||
|
| ((bytes[pos++] & 0xFF) << 8) | (bytes[pos++] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigInteger decodeBigInt() {
|
||||||
|
int len = decodeInt();
|
||||||
|
byte[] bigIntBytes = new byte[len];
|
||||||
|
System.arraycopy(bytes, pos, bigIntBytes, 0, len);
|
||||||
|
pos += len;
|
||||||
|
return new BigInteger(bigIntBytes);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.sshd.server.PublickeyAuthenticator;
|
||||||
|
import org.apache.sshd.server.session.ServerSession;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class PublicKeyAuthenticator implements PublickeyAuthenticator {
|
||||||
|
private File 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);
|
||||||
|
|
||||||
|
if (keyFile.exists()) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SshdPlugin.instance.getLogger().severe("Failed to parse PEM file. " + keyFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
SshdPlugin.instance.getLogger().severe("Failed to process public key " + keyFile.getAbsolutePath() + ". " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SshdPlugin.instance.getLogger().warning("Could not locate public key for " + username + ". Make sure the user's key is named the same as their user name without a file extension.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
98
src/main/java/com/ryanmichela/sshd/ReflectionUtil.java
Normal file
98
src/main/java/com/ryanmichela/sshd/ReflectionUtil.java
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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 ex) {
|
||||||
|
System.out.println("*** " + c.getName() + ":" + ex);
|
||||||
|
} catch (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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/main/java/com/ryanmichela/sshd/SshTerminal.java
Normal file
19
src/main/java/com/ryanmichela/sshd/SshTerminal.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.bukkit.craftbukkit.libs.jline.TerminalSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class SshTerminal extends TerminalSupport {
|
||||||
|
|
||||||
|
protected SshTerminal() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws Exception {
|
||||||
|
setAnsiSupported(true);
|
||||||
|
setEchoEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
62
src/main/java/com/ryanmichela/sshd/SshdPlugin.java
Normal file
62
src/main/java/com/ryanmichela/sshd/SshdPlugin.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.SshServer;
|
||||||
|
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class SshdPlugin extends JavaPlugin {
|
||||||
|
private SshServer sshd;
|
||||||
|
public static SshdPlugin instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
saveDefaultConfig();
|
||||||
|
File authorizedKeys = new File(getDataFolder(), "authorized_keys");
|
||||||
|
if (!authorizedKeys.exists()) {
|
||||||
|
authorizedKeys.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
instance = this;
|
||||||
|
|
||||||
|
sshd = SshServer.setUpDefaultServer();
|
||||||
|
sshd.setPort(getConfig().getInt("port", 22));
|
||||||
|
|
||||||
|
File hostKey = new File(getDataFolder(), "hostkey");
|
||||||
|
File authorizedKeys = new File(getDataFolder(), "authorized_keys");
|
||||||
|
|
||||||
|
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKey.getPath()));
|
||||||
|
sshd.setShellFactory(new ConsoleShellFactory());
|
||||||
|
sshd.setPasswordAuthenticator(new ConfigPasswordAuthenticator());
|
||||||
|
sshd.setPublickeyAuthenticator(new PublicKeyAuthenticator(authorizedKeys));
|
||||||
|
sshd.setCommandFactory(new ConsoleCommandFactory());
|
||||||
|
try {
|
||||||
|
sshd.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
getLogger().severe("Failed to start SSH server! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
try {
|
||||||
|
sshd.stop();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/main/java/com/ryanmichela/sshd/Waitable.java
Normal file
48
src/main/java/com/ryanmichela/sshd/Waitable.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public abstract class Waitable<T> implements Runnable {
|
||||||
|
private enum Status {
|
||||||
|
WAITING,
|
||||||
|
RUNNING,
|
||||||
|
FINISHED,
|
||||||
|
}
|
||||||
|
Throwable t = null;
|
||||||
|
T value = null;
|
||||||
|
Status status = Status.WAITING;
|
||||||
|
|
||||||
|
public final void run() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (status != Status.WAITING) {
|
||||||
|
throw new IllegalStateException("Invalid state " + status);
|
||||||
|
}
|
||||||
|
status = Status.RUNNING;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
value = evaluate();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
this.t = t;
|
||||||
|
} finally {
|
||||||
|
synchronized (this) {
|
||||||
|
status = Status.FINISHED;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T evaluate();
|
||||||
|
|
||||||
|
public synchronized T get() throws InterruptedException, ExecutionException {
|
||||||
|
while (status != Status.FINISHED) {
|
||||||
|
this.wait();
|
||||||
|
}
|
||||||
|
if (t != null) {
|
||||||
|
throw new ExecutionException(t);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
353
src/main/java/org/slf4j/impl/PluginSlf4jFactory.java
Normal file
353
src/main/java/org/slf4j/impl/PluginSlf4jFactory.java
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
package org.slf4j.impl;
|
||||||
|
|
||||||
|
import com.ryanmichela.sshd.SshdPlugin;
|
||||||
|
import org.slf4j.ILoggerFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.Marker;
|
||||||
|
import org.slf4j.helpers.FormattingTuple;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2013 Ryan Michela
|
||||||
|
*/
|
||||||
|
public class PluginSlf4jFactory implements ILoggerFactory {
|
||||||
|
@Override
|
||||||
|
public Logger getLogger(String name) {
|
||||||
|
return new PluginSlf4jAdapter(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PluginSlf4jAdapter implements Logger {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private boolean isEnabled(Level level) {
|
||||||
|
if (SshdPlugin.instance != null) {
|
||||||
|
return SshdPlugin.instance.getLogger().isLoggable(level);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(Level level, String s, Object[] objects) {
|
||||||
|
if (SshdPlugin.instance != null && isEnabled(level)) {
|
||||||
|
FormattingTuple ft = MessageFormatter.arrayFormat(s, objects);
|
||||||
|
SshdPlugin.instance.getLogger().log(level, ft.getMessage(), ft.getThrowable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(Level level, String s, Throwable throwable) {
|
||||||
|
if (SshdPlugin.instance != null && isEnabled(level)) {
|
||||||
|
SshdPlugin.instance.getLogger().log(level, s, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginSlf4jAdapter(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTraceEnabled() {
|
||||||
|
return isEnabled(Level.FINEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String s) {
|
||||||
|
trace(s, new Object[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String s, Object o) {
|
||||||
|
trace(s, new Object[]{o});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String s, Object o, Object o1) {
|
||||||
|
trace(s, new Object[]{o, o1});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String s, Object[] objects) {
|
||||||
|
log(Level.FINEST, s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String s, Throwable throwable) {
|
||||||
|
log(Level.FINEST, s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTraceEnabled(Marker marker) {
|
||||||
|
return isTraceEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(Marker marker, String s) {
|
||||||
|
trace(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(Marker marker, String s, Object o) {
|
||||||
|
trace(s, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(Marker marker, String s, Object o, Object o1) {
|
||||||
|
trace(s, o, o1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(Marker marker, String s, Object[] objects) {
|
||||||
|
trace(s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(Marker marker, String s, Throwable throwable) {
|
||||||
|
trace(s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDebugEnabled() {
|
||||||
|
return isEnabled(Level.FINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String s) {
|
||||||
|
debug(s, new Object[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String s, Object o) {
|
||||||
|
debug(s, new Object[]{o});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String s, Object o, Object o1) {
|
||||||
|
debug(s, new Object[]{o, o1});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String s, Object[] objects) {
|
||||||
|
log(Level.FINE, s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String s, Throwable throwable) {
|
||||||
|
log(Level.FINE, s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDebugEnabled(Marker marker) {
|
||||||
|
return isDebugEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Marker marker, String s) {
|
||||||
|
debug(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Marker marker, String s, Object o) {
|
||||||
|
debug(s, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Marker marker, String s, Object o, Object o1) {
|
||||||
|
debug(s, o, o1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Marker marker, String s, Object[] objects) {
|
||||||
|
debug(s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(Marker marker, String s, Throwable throwable) {
|
||||||
|
debug(s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInfoEnabled() {
|
||||||
|
return isEnabled(Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String s) {
|
||||||
|
info(s, new Object[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String s, Object o) {
|
||||||
|
info(s, new Object[]{o});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String s, Object o, Object o1) {
|
||||||
|
info(s, new Object[]{o, o1});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String s, Object[] objects) {
|
||||||
|
log(Level.INFO, s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String s, Throwable throwable) {
|
||||||
|
log(Level.INFO, s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInfoEnabled(Marker marker) {
|
||||||
|
return isInfoEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(Marker marker, String s) {
|
||||||
|
info(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(Marker marker, String s, Object o) {
|
||||||
|
info(s, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(Marker marker, String s, Object o, Object o1) {
|
||||||
|
info(s, o, o1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(Marker marker, String s, Object[] objects) {
|
||||||
|
info(s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(Marker marker, String s, Throwable throwable) {
|
||||||
|
info(s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWarnEnabled() {
|
||||||
|
return isEnabled(Level.WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String s) {
|
||||||
|
warn(s, new Object[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String s, Object o) {
|
||||||
|
warn(s, new Object[]{o});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String s, Object o, Object o1) {
|
||||||
|
warn(s, new Object[]{o, o1});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String s, Object[] objects) {
|
||||||
|
log(Level.WARNING, s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(String s, Throwable throwable) {
|
||||||
|
log(Level.WARNING, s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWarnEnabled(Marker marker) {
|
||||||
|
return isWarnEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(Marker marker, String s) {
|
||||||
|
warn(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(Marker marker, String s, Object o) {
|
||||||
|
warn(s, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(Marker marker, String s, Object o, Object o1) {
|
||||||
|
warn(s, o, o1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(Marker marker, String s, Object[] objects) {
|
||||||
|
warn(s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warn(Marker marker, String s, Throwable throwable) {
|
||||||
|
warn(s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isErrorEnabled() {
|
||||||
|
return isEnabled(Level.SEVERE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String s) {
|
||||||
|
error(s, new Object[]{});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String s, Object o) {
|
||||||
|
error(s, new Object[]{o});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String s, Object o, Object o1) {
|
||||||
|
error(s, new Object[]{o, o1});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String s, Object[] objects) {
|
||||||
|
log(Level.SEVERE, s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String s, Throwable throwable) {
|
||||||
|
log(Level.SEVERE, s, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isErrorEnabled(Marker marker) {
|
||||||
|
return isErrorEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Marker marker, String s) {
|
||||||
|
error(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Marker marker, String s, Object o) {
|
||||||
|
error(s, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Marker marker, String s, Object o, Object o1) {
|
||||||
|
error(s, o, o1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Marker marker, String s, Object[] objects) {
|
||||||
|
error(s, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(Marker marker, String s, Throwable throwable) {
|
||||||
|
error(s, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
src/main/java/org/slf4j/impl/StaticLoggerBinder.java
Normal file
82
src/main/java/org/slf4j/impl/StaticLoggerBinder.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2004-2011 QOS.ch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.slf4j.impl;
|
||||||
|
|
||||||
|
import org.slf4j.ILoggerFactory;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.spi.LoggerFactoryBinder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The binding of {@link LoggerFactory} class with an actual instance of
|
||||||
|
* {@link ILoggerFactory} is performed using information returned by this class.
|
||||||
|
*
|
||||||
|
* @author Ceki Gülcü
|
||||||
|
*/
|
||||||
|
public class StaticLoggerBinder implements LoggerFactoryBinder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique instance of this class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton of this class.
|
||||||
|
*
|
||||||
|
* @return the StaticLoggerBinder singleton
|
||||||
|
*/
|
||||||
|
public static final StaticLoggerBinder getSingleton() {
|
||||||
|
return SINGLETON;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare the version of the SLF4J API this implementation is compiled against.
|
||||||
|
* The value of this field is usually modified with each release.
|
||||||
|
*/
|
||||||
|
// to avoid constant folding by the compiler, this field must *not* be final
|
||||||
|
public static String REQUESTED_API_VERSION = "1.6.99"; // !final
|
||||||
|
|
||||||
|
|
||||||
|
private static final String loggerFactoryClassStr = PluginSlf4jFactory.class.getName();
|
||||||
|
|
||||||
|
/** The ILoggerFactory instance returned by the {@link #getLoggerFactory} method
|
||||||
|
* should always be the same object
|
||||||
|
*/
|
||||||
|
private final ILoggerFactory loggerFactory;
|
||||||
|
|
||||||
|
private StaticLoggerBinder() {
|
||||||
|
// Note: JCL gets substituted at build time by an appropriate Ant task
|
||||||
|
loggerFactory = new PluginSlf4jFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILoggerFactory getLoggerFactory() {
|
||||||
|
return loggerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLoggerFactoryClassStr() {
|
||||||
|
return loggerFactoryClassStr;
|
||||||
|
}
|
||||||
|
}
|
12
src/main/resources/config.yml
Normal file
12
src/main/resources/config.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# This is the port the SSH server will listen on.
|
||||||
|
port: 22
|
||||||
|
|
||||||
|
# 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).
|
||||||
|
|
||||||
|
# For less secure username and password based authentication, complete the sections below.
|
||||||
|
credentials:
|
||||||
|
# user1: password1
|
||||||
|
# user2: password2
|
4
src/main/resources/plugin.yml
Normal file
4
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
name: SSHD
|
||||||
|
version: "1.0"
|
||||||
|
author: Ryan Michela
|
||||||
|
main: com.ryanmichela.sshd.SshdPlugin
|
Loading…
Reference in New Issue
Block a user