From 7176936a62258be83becf7960ed045200419ab4d Mon Sep 17 00:00:00 2001
From: Or Cohen <orc@fewbytes.com>
Date: Wed, 21 Aug 2013 17:36:07 +0300
Subject: [PATCH] Initial implementation for SSHD

A straightfoward implementation for SSHD
Supports SCP, SFTP subsystem and a shell through the current JS cli
---
 java/build.xml                                | 32 +++++++++-
 .../com/cloudius/sshd/RhinoCLICommand.java    | 58 ++++++++++++++++++
 .../com/cloudius/sshd/RhinoShellFactory.java  | 18 ++++++
 java/sshd/com/cloudius/sshd/Server.java       | 61 +++++++++++++++++++
 java/sshd/com/cloudius/sshd/Stty.java         | 17 ++++++
 java/sshd/com/cloudius/sshd/Tty.java          | 41 +++++++++++++
 6 files changed, 225 insertions(+), 2 deletions(-)
 create mode 100644 java/sshd/com/cloudius/sshd/RhinoCLICommand.java
 create mode 100644 java/sshd/com/cloudius/sshd/RhinoShellFactory.java
 create mode 100644 java/sshd/com/cloudius/sshd/Server.java
 create mode 100644 java/sshd/com/cloudius/sshd/Stty.java
 create mode 100644 java/sshd/com/cloudius/sshd/Tty.java

diff --git a/java/build.xml b/java/build.xml
index e9ce99a0a..4c0193fd5 100644
--- a/java/build.xml
+++ b/java/build.xml
@@ -4,18 +4,33 @@
         simple example build file
     </description>
   <!-- set global properties for this build -->
+  <property name="external" location="../external"/>
+  <property name="external-lib" location="${external}/jars.bin"/>
   <property name="src-cloudius" location="cloudius/"/>
   <property name="src-cli" location="cli/"/>
+  <property name="src-sshd" location="sshd"/>
   <property name="build-cloudius" location="${out}/classes-cloudius"/>
   <property name="build-cli" location="${out}/classes-cli"/>
+  <property name="build-sshd" location="${out}/classes-sshd"/>
+  <property name="jars-sshd" value="bcprov-jdk15-140.jar mina-core-2.0.5.jar slf4j-api-1.7.5.jar slf4j-simple-1.7.5.jar sshd-core-0.8.0.jar sshd-pam-0.8.0.jar tomcat-apr-5.5.23.jar" />
+  
+  <script language="javascript">
+  	var jars_sshd_with_lib = project.getProperty('jars-sshd')
+  		.split(' ').map(function(jar) { return "lib/" + jar; })
+  		.join(' ');
+  	project.setProperty('jars-lib-sshd', jars_sshd_with_lib)
+  </script>
+	
   <property name="dist" location="${out}"/>
-
+	
   <target name="init">
     <!-- Create the build directory structure used by compile -->
     <mkdir dir="${build-cloudius}"/>
     <mkdir dir="${build-cloudius}/META-INF"/>
     <mkdir dir="${build-cli}"/>
     <mkdir dir="${build-cli}/META-INF"/>
+    <mkdir dir="${build-sshd}"/>
+    <mkdir dir="${build-sshd}/META-INF"/>
   </target>
 
   <target name="compile" depends="init"
@@ -25,17 +40,29 @@
     <javac includeantruntime="false" srcdir="${src-cli}" destdir="${build-cli}">
       <classpath path="${build-cloudius}" />
     </javac>
+    <javac includeantruntime="false" srcdir="${src-sshd}" destdir="${build-sshd}">
+      <classpath>
+      	<path path="${build-cloudius}" />
+      	<path path="${build-cli}" />
+      	<fileset dir="${external-lib}" includes="${jars-sshd}" />
+      </classpath>
+    </javac>
   </target>
 
   <target name="dist" depends="compile"
         description="generate the distribution" >
-
     <jar jarfile="${dist}/cloudius.jar" basedir="${build-cloudius}" compress="false" />
     <jar jarfile="${dist}/cli.jar" basedir="${build-cli}" compress="false" >
       <manifest>
         <attribute name="Main-Class" value="com.cloudius.cli.main.RhinoCLI" />
         <attribute name="Class-Path" value="cloudius.jar" />
       </manifest>
+    </jar>
+  	<jar jarfile="${dist}/sshd.jar" basedir="${build-sshd}" compress="false">
+  	  <manifest>
+  	  	<attribute name="Main-Class" value="com.cloudius.sshd.Server" />
+  	  	<attribute name="Class-Path" value="cli.jar ${jars-lib-sshd}" />
+  	  </manifest>
     </jar>
   </target>
 
@@ -44,6 +71,7 @@
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build-cloudius}"/>
     <delete dir="${build-cli}"/>
+    <delete dir="${build-sshd}"/>
     <delete dir="${dist}"/>
   </target>
 </project>
diff --git a/java/sshd/com/cloudius/sshd/RhinoCLICommand.java b/java/sshd/com/cloudius/sshd/RhinoCLICommand.java
new file mode 100644
index 000000000..7b22750fd
--- /dev/null
+++ b/java/sshd/com/cloudius/sshd/RhinoCLICommand.java
@@ -0,0 +1,58 @@
+package com.cloudius.sshd;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+
+import com.cloudius.cli.main.RhinoCLI;
+
+public class RhinoCLICommand implements Command {
+
+    private Thread cliThread;
+    final Tty tty = new Tty();
+
+    public RhinoCLICommand(String cliJs) {
+        this.cliThread = new RhinoCLIThread();
+    }
+
+    class RhinoCLIThread extends Thread {
+        @Override
+        public void run() {
+            String[] args = {};
+            RhinoCLI.run(tty, false, args);
+        }
+    }
+
+    @Override
+    public void start(Environment env) {
+        cliThread.start();
+    }
+
+    @Override
+    public void setOutputStream(OutputStream out) {
+        tty.setOut(out);
+    }
+
+    @Override
+    public void setInputStream(InputStream in) {
+        tty.setIn(in);
+    }
+
+    @Override
+    public void setExitCallback(ExitCallback callback) {
+    }
+
+    @Override
+    public void setErrorStream(OutputStream err) {
+        tty.setErr(err);
+    }
+
+    @Override
+    public void destroy() {
+        cliThread.interrupt();
+    }
+
+}
diff --git a/java/sshd/com/cloudius/sshd/RhinoShellFactory.java b/java/sshd/com/cloudius/sshd/RhinoShellFactory.java
new file mode 100644
index 000000000..695b97bbf
--- /dev/null
+++ b/java/sshd/com/cloudius/sshd/RhinoShellFactory.java
@@ -0,0 +1,18 @@
+package com.cloudius.sshd;
+
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.server.Command;
+
+public class RhinoShellFactory implements Factory<Command> {
+    String cliJs;
+
+    public RhinoShellFactory(String cliJs) {
+        this.cliJs = cliJs;
+    }
+
+    @Override
+    public Command create() {
+        return new RhinoCLICommand(cliJs);
+    }
+
+}
diff --git a/java/sshd/com/cloudius/sshd/Server.java b/java/sshd/com/cloudius/sshd/Server.java
new file mode 100644
index 000000000..0d9fc3cc6
--- /dev/null
+++ b/java/sshd/com/cloudius/sshd/Server.java
@@ -0,0 +1,61 @@
+package com.cloudius.sshd;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.sftp.SftpSubsystem;
+
+public class Server {
+    public static final String DEFAULT_PORT = "22";
+    public static final String DEFAULT_HOSTKEY = "/etc/hostkey.est";
+    public static final String DEFAULT_CONSOLE_CLI = "/console/cli.js";
+
+    public static final String SYSTEM_PREFIX = "com.cloudius.sshd.";
+
+    public static final String SYSTEM_PROP_PORT = SYSTEM_PREFIX + "port";
+    public static final String SYSTEM_PROP_HOSTKEY = SYSTEM_PREFIX + "hostkey";
+    public static final String SYSTEM_PROP_CONSOLE_CLI = SYSTEM_PREFIX
+            + "console.cli";
+
+    public static void main(String[] args) throws IOException {
+        SshServer sshServer = SshServer.setUpDefaultServer();
+
+        sshServer.setPort(Integer.parseInt(System.getProperty(SYSTEM_PROP_PORT,
+                DEFAULT_PORT)));
+
+        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(System
+                .getProperty(SYSTEM_PROP_HOSTKEY, DEFAULT_HOSTKEY)));
+
+        // Support SCP
+        sshServer.setCommandFactory(new ScpCommandFactory());
+
+        // Support SFTP subsystem
+        ArrayList<NamedFactory<Command>> subsystemFactoriesList = new ArrayList<NamedFactory<Command>>(
+                1);
+        subsystemFactoriesList.add(new SftpSubsystem.Factory());
+        sshServer.setSubsystemFactories(subsystemFactoriesList);
+
+        // Set shell factory to Rhino
+        sshServer.setShellFactory(new RhinoShellFactory(System.getProperty(
+                SYSTEM_PROP_CONSOLE_CLI, DEFAULT_CONSOLE_CLI)));
+
+        // Basic non-existend authentication
+        sshServer.setPasswordAuthenticator(new PasswordAuthenticator() {
+            @Override
+            public boolean authenticate(String arg0, String arg1,
+                    ServerSession arg2) {
+                // TODO Implement authentication
+                return true;
+            }
+        });
+
+        sshServer.start();
+    }
+}
diff --git a/java/sshd/com/cloudius/sshd/Stty.java b/java/sshd/com/cloudius/sshd/Stty.java
new file mode 100644
index 000000000..4ed5f9469
--- /dev/null
+++ b/java/sshd/com/cloudius/sshd/Stty.java
@@ -0,0 +1,17 @@
+package com.cloudius.sshd;
+
+import com.cloudius.util.IStty;
+
+public class Stty implements IStty {
+    @Override
+    public void reset() {
+    }
+
+    @Override
+    public void close() throws Exception {
+    }
+
+    @Override
+    public void raw() {
+    }
+}
diff --git a/java/sshd/com/cloudius/sshd/Tty.java b/java/sshd/com/cloudius/sshd/Tty.java
new file mode 100644
index 000000000..e840e3ef0
--- /dev/null
+++ b/java/sshd/com/cloudius/sshd/Tty.java
@@ -0,0 +1,41 @@
+package com.cloudius.sshd;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.cloudius.cli.main.RhinoCLI;
+
+public class Tty implements RhinoCLI.TTY {
+    InputStream in;
+    OutputStream out;
+    OutputStream err;
+    Stty stty = new Stty();
+
+    public InputStream getIn() {
+        return in;
+    }
+
+    public void setIn(InputStream in) {
+        this.in = in;
+    }
+
+    public OutputStream getOut() {
+        return out;
+    }
+
+    public void setOut(OutputStream out) {
+        this.out = out;
+    }
+
+    public OutputStream getErr() {
+        return err;
+    }
+
+    public void setErr(OutputStream err) {
+        this.err = err;
+    }
+
+    public Stty getStty() {
+        return stty;
+    }
+}
-- 
GitLab