geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jason Dillon <jason.dil...@gmail.com>
Subject Re: [Heads up] SSH server in java
Date Sat, 22 Nov 2008 12:05:40 GMT
On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
> On Sat, Nov 22, 2008 at 7:32 AM, Jason Dillon  
> <jason.dillon@gmail.com> wrote:
>> Any idea what this means:
>>
>> <snip>
>> Bliss:Applications jason$ ssh localhost -p 8081
>> jason@localhost's password:
>> channel_by_id: 1: bad id: channel free
>> channel_input_success_failure: 1: unknown
>> channel_by_id: 1: bad id: channel free
>> channel_input_success_failure: 1: unknown
>> </snip>
>>
>> This is from "OpenSSH_5.1p1, OpenSSL 0.9.7l 28 Sep 2006" on Mac OS  
>> X.  It
>> does connect and seems to work well.  Though seems to not handle  
>> sending
>> over exceptions, like when a command is not resolved.  But I might  
>> look into
>> that some more later today.
>
> Not sure what those lines mean.  When I connect using OpenSSH and
> launch a bad command in ServiceMix, I can see the usual output from
> gshell on stderr with the ansi colors.

Kay, I've not idea either, they just poppeed out so I forwarded them  
on to you.


>> Whats the status of the SSH work, any release on the horizon?  I'm  
>> sold on
>> this for the GShell remoting direction, and really this is what I  
>> wanted
>> from the start.  So I'd like to drop the other whisper/remoting  
>> muck and
>> just use this.
>
> There are still lots of things to do, but i think i could release a
> 0.1 very soon.
> Btw, this project should soon move into Apache as a Mina subproject,
> but I will do a release before that at google so that we can embed it.


Cool, a 0.1 would be awesome as soon as you can craft it.

--jason



>> Your thoughts?
>>
>> --jason
>>
>>
>> On Nov 13, 2008, at 5:58 AM, Guillaume Nodet wrote:
>>
>>> I've just done a real quick prototype to plug into smx kernel and  
>>> I've
>>> been able to log in into smx kernel using an ssh client and issue a
>>> few commands.
>>> Following is the class that does everything and the spring config to
>>> start the ssh server.
>>> The BogusPasswordAuthenticator is a dummy class which I pasted  
>>> below too.
>>>
>>> Notice the use of stream filters to convert CR / CRLF stuff.  I  
>>> think
>>> this is because both sshd and the geronimo gshell do not handle well
>>> the pty request and/or VT100 stuff.  But I'm still not sure where  
>>> the
>>> conversion should happen exactly.
>>>
>>> Also note that i've redefined the ConsoleErrorHandlerImpl, because  
>>> the
>>> default one uses the application.getIO() for displaying errors so  
>>> they
>>> are not available remotely.
>>>
>>> Let me know what you think, but it basically makes the whole remote
>>> bits of gshell unused.
>>> I have not implemented the ssh command which should be easy using  
>>> jsch
>>> lib.
>>>
>>> Let me know if / how I can help you with that bits.
>>>
>>> ==================================================
>>> package org.apache.servicemix.kernel.gshell.core.sshd;
>>>
>>> import com.google.code.sshd.PasswordAuthenticator;
>>>
>>> public class BogusPasswordAuthenticator implements  
>>> PasswordAuthenticator {
>>>
>>>  public Object authenticate(String username, String password) {
>>>      return (username != null && username.equals(password)) ?
>>> username : null;
>>>  }
>>> }
>>>
>>>
>>> ==================================================
>>>  <bean name="sshServer" class="com.google.code.sshd.SshServer"
>>> init-method="start" destroy-method="stop">
>>>      <property name="port" value="8000" />
>>>      <property name="shellFactory">
>>>          <bean
>>> class 
>>> ="org.apache.servicemix.kernel.gshell.core.sshd.GShellShellFactory">
>>>              <property name="branding" ref="branding" />
>>>              <property name="completers">
>>>                  <list>
>>>                      <ref bean="commandsCompleter"/>
>>>                      <ref bean="aliasNameCompleter"/>
>>>                  </list>
>>>              </property>
>>>              <property name="executor" ref="commandLineExecutor" />
>>>              <property name="history">
>>>                  <bean
>>> class="org.apache.geronimo.gshell.wisdom.shell.HistoryImpl">
>>>                      <constructor-arg ref="application"/>
>>>                  </bean>
>>>              </property>
>>>              <property name="prompter">
>>>                  <bean
>>> class="org.apache.geronimo.gshell.wisdom.shell.ConsolePrompterImpl">
>>>                      <constructor-arg ref="application"/>
>>>                  </bean>
>>>              </property>
>>>          </bean>
>>>      </property>
>>>      <property name="hostKeyProvider">
>>>          <bean  
>>> class="com.google.code.sshd.hostkeys.FileHostKeyProvider">
>>>              <constructor-arg>
>>>                  <list>
>>>                      <value>${hostKey}</value>
>>>                  </list>
>>>              </constructor-arg>
>>>          </bean>
>>>      </property>
>>>      <property name="passwordAuthenticator">
>>>          <!-- TODO: provide real authentication -->
>>>          <bean
>>>
>>> class 
>>> = 
>>> "org 
>>> .apache 
>>> .servicemix.kernel.gshell.core.sshd.BogusPasswordAuthenticator"
>>> />
>>>      </property>
>>>      <!-- Do not use public keys for now
>>>      <property name="publickeyAuthenticator">
>>>          <bean  
>>> class="com.google.code.sshd.BogusPublickeyAuthenticator"
>>> />
>>>      </property>
>>>      -->
>>>      <!-- Standard properties -->
>>>      <property name="channelFactories">
>>>          <list>
>>>              <bean
>>> class="com.google.code.sshd.channel.ChannelSession$Factory" />
>>>          </list>
>>>      </property>
>>>      <property name="cipherFactories">
>>>          <list>
>>>              <bean class="com.google.code.sshd.cipher.AES128CBC 
>>> $Factory"
>>> />
>>>              <bean
>>> class="com.google.code.sshd.cipher.TripleDESCBC$Factory" />
>>>              <bean
>>> class="com.google.code.sshd.cipher.BlowfishCBC$Factory" />
>>>              <bean class="com.google.code.sshd.cipher.AES192CBC 
>>> $Factory"
>>> />
>>>              <bean class="com.google.code.sshd.cipher.AES256CBC 
>>> $Factory"
>>> />
>>>          </list>
>>>      </property>
>>>      <property name="compressionFactories">
>>>          <list>
>>>              <bean
>>> class="com.google.code.sshd.compression.CompressionNone$Factory" />
>>>          </list>
>>>      </property>
>>>      <property name="keyExchangeFactories">
>>>          <list>
>>>              <bean class="com.google.code.sshd.kex.DHG1$Factory" />
>>>          </list>
>>>      </property>
>>>      <property name="macFactories">
>>>          <list>
>>>              <bean  
>>> class="com.google.code.sshd.mac.HMACMD5$Factory" />
>>>              <bean  
>>> class="com.google.code.sshd.mac.HMACSHA1$Factory" />
>>>              <bean  
>>> class="com.google.code.sshd.mac.HMACMD596$Factory" />
>>>              <bean  
>>> class="com.google.code.sshd.mac.HMACSHA196$Factory" />
>>>          </list>
>>>      </property>
>>>      <property name="randomFactory">
>>>          <bean class="com.google.code.sshd.random.JceRandom 
>>> $Factory" />
>>>      </property>
>>>      <property name="userAuthFactories">
>>>          <list>
>>>              <bean
>>> class="com.google.code.sshd.auth.UserAuthPublicKey$Factory" />
>>>              <bean
>>> class="com.google.code.sshd.auth.UserAuthPassword$Factory" />
>>>          </list>
>>>      </property>
>>>      <property name="signatureFactories">
>>>          <list>
>>>              <bean
>>> class="com.google.code.sshd.signature.SignatureDSA$Factory" />
>>>              <bean
>>> class="com.google.code.sshd.signature.SignatureRSA$Factory" />
>>>          </list>
>>>      </property>
>>>  </bean>
>>>
>>>
>>>
>>> ===================================================
>>> package org.apache.servicemix.kernel.gshell.core.sshd;
>>>
>>> import java.util.Map;
>>> import java.util.List;
>>> import java.io.OutputStream;
>>> import java.io.InputStream;
>>> import java.io.Closeable;
>>> import java.io.IOException;
>>>
>>> import com.google.code.sshd.ShellFactory;
>>> import com.google.code.sshd.shell.CrLfFilterInputStream;
>>> import org.apache.geronimo.gshell.shell.ShellContext;
>>> import org.apache.geronimo.gshell.io.IO;
>>> import org.apache.geronimo.gshell.command.Variables;
>>> import org.apache.geronimo.gshell.console.Console;
>>> import org.apache.geronimo.gshell.console.JLineConsole;
>>> import  
>>> org.apache.geronimo.gshell.console.completer.AggregateCompleter;
>>> import org.apache.geronimo.gshell.notification.ExitNotification;
>>> import org.apache.geronimo.gshell.notification.ErrorNotification;
>>> import org.apache.geronimo.gshell.application.model.Branding;
>>> import org.apache.geronimo.gshell.commandline.CommandLineExecutor;
>>> import org.apache.geronimo.gshell.ansi.AnsiRenderer;
>>> import org.slf4j.LoggerFactory;
>>> import org.slf4j.Logger;
>>> import jline.History;
>>> import jline.Completor;
>>>
>>> public class GShellShellFactory implements ShellFactory {
>>>
>>>  private Logger logger = LoggerFactory.getLogger(getClass());
>>>  private Branding branding;
>>>  private Console.Prompter prompter;
>>>  private CommandLineExecutor executor;
>>>  private History history;
>>>  private List<Completor> completers;
>>>
>>>  public Branding getBranding() {
>>>      return branding;
>>>  }
>>>
>>>  public void setBranding(Branding branding) {
>>>      this.branding = branding;
>>>  }
>>>
>>>  public Console.Prompter getPrompter() {
>>>      return prompter;
>>>  }
>>>
>>>  public void setPrompter(Console.Prompter prompter) {
>>>      this.prompter = prompter;
>>>  }
>>>
>>>  public CommandLineExecutor getExecutor() {
>>>      return executor;
>>>  }
>>>
>>>  public void setExecutor(CommandLineExecutor executor) {
>>>      this.executor = executor;
>>>  }
>>>
>>>  public History getHistory() {
>>>      return history;
>>>  }
>>>
>>>  public void setHistory(History history) {
>>>      this.history = history;
>>>  }
>>>
>>>  public List<Completor> getCompleters() {
>>>      return completers;
>>>  }
>>>
>>>  public void setCompleters(List<Completor> completers) {
>>>      this.completers = completers;
>>>  }
>>>
>>>  public Shell createShell() {
>>>      return new ShellImpl();
>>>  }
>>>
>>>  public class ShellImpl implements ShellFactory.DirectShell,
>>> org.apache.geronimo.gshell.shell.Shell {
>>>
>>>      private InputStream in;
>>>      private OutputStream out;
>>>      private OutputStream err;
>>>      private IO io;
>>>      private Variables variables;
>>>      private ShellContext context;
>>>      private boolean closed;
>>>
>>>      public ShellImpl() {
>>>      }
>>>
>>>      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 start(Map<String,String> env) throws Exception {
>>>          this.io = new IO(new CrLfFilterInputStream(in, "IN: ",  
>>> logger),
>>>                           new LfToCrLfFilterOutputStream(out,
>>> "OUT:", logger),
>>>                           new LfToCrLfFilterOutputStream(err,
>>> "ERR:", logger),
>>>                           false);
>>>          this.variables = new Variables((Map) env);
>>>          this.context = new ShellContext() {
>>>              public org.apache.geronimo.gshell.shell.Shell  
>>> getShell() {
>>>                  return ShellImpl.this;
>>>              }
>>>              public IO getIo() {
>>>                  return ShellImpl.this.io;
>>>              }
>>>              public Variables getVariables() {
>>>                  return ShellImpl.this.variables;
>>>              }
>>>          };
>>>          new Thread() {
>>>              public void run() {
>>>                  try {
>>>                      ShellImpl.this.run();
>>>                  } catch (Exception e) {
>>>                      e.printStackTrace();
>>>                  } finally {
>>>                      close();
>>>                  }
>>>              }
>>>          }.start();
>>>      }
>>>
>>>      public boolean isAlive() {
>>>          return !closed;
>>>      }
>>>
>>>      public int exitValue() {
>>>          if (!closed) {
>>>              throw new IllegalThreadStateException();
>>>          }
>>>          return 0;
>>>      }
>>>
>>>      public void destroy() {
>>>          close();
>>>      }
>>>
>>>      public ShellContext getContext() {
>>>          return context;
>>>      }
>>>
>>>      public Object execute(String line) throws Exception {
>>>          return executor.execute(getContext(), line);
>>>      }
>>>
>>>      public Object execute(String command, Object[] args) throws
>>> Exception {
>>>          return executor.execute(getContext(), args);
>>>      }
>>>
>>>      public Object execute(Object... args) throws Exception {
>>>          return executor.execute(getContext(), args);
>>>      }
>>>
>>>      public boolean isOpened() {
>>>          return !closed;
>>>      }
>>>
>>>      public void close() {
>>>          closed = true;
>>>          close(in);
>>>          close(out);
>>>          close(err);
>>>      }
>>>
>>>      public boolean isInteractive() {
>>>          return false;
>>>      }
>>>
>>>      public void run(Object... args) throws Exception {
>>>          Console.Executor executor = new Console.Executor() {
>>>              public Result execute(final String line) throws  
>>> Exception {
>>>                  assert line != null;
>>>                  try {
>>>                      ShellImpl.this.execute(line);
>>>                  }
>>>                  catch (ExitNotification n) {
>>>                      return Result.STOP;
>>>                  }
>>>                  return Result.CONTINUE;
>>>              }
>>>          };
>>>
>>>          IO io = getContext().getIo();
>>>
>>>          // Setup the console runner
>>>          JLineConsole console = new JLineConsole(executor, io);
>>>          console.setPrompter(getPrompter());
>>>          console.setErrorHandler(new ConsoleErrorHandlerImpl(io));
>>>          console.setHistory(getHistory());
>>>          if (completers != null) {
>>>              // Have to use aggregate here to get the completion
>>> list to update properly
>>>              console.addCompleter(new  
>>> AggregateCompleter(completers));
>>>          }
>>>          console.run();
>>>      }
>>>
>>>      private void close(Closeable c) {
>>>          try {
>>>              c.close();
>>>          } catch (IOException e) {
>>>              // Ignore
>>>          }
>>>      }
>>>
>>>  }
>>>
>>>  public static class ConsoleErrorHandlerImpl implements
>>> Console.ErrorHandler {
>>>      private final Logger log = LoggerFactory.getLogger(getClass());
>>>
>>>      private final IO io;
>>>
>>>      private AnsiRenderer renderer = new AnsiRenderer();
>>>
>>>      public ConsoleErrorHandlerImpl(final IO io) {
>>>          assert io != null;
>>>          this.io = io;
>>>      }
>>>
>>>      public Result handleError(final Throwable error) {
>>>          assert error != null;
>>>
>>>          displayError(error);
>>>
>>>          return Result.CONTINUE;
>>>      }
>>>
>>>      private void displayError(final Throwable error) {
>>>          assert error != null;
>>>
>>>          // Decode any error notifications
>>>          Throwable cause = error;
>>>          if (error instanceof ErrorNotification) {
>>>              cause = error.getCause();
>>>          }
>>>
>>>          //
>>>          // TODO: Use the Render API
>>>          //
>>>
>>>          // Spit out the terse reason why we've failed
>>>          io.err.print("@|bold,red ERROR| ");
>>>          io.err.print(cause.getClass().getSimpleName());
>>>          io.err.println(": @|bold,red " + cause.getMessage() + "|");
>>>
>>>          // Determine if the stack trace flag is set
>>>          String stackTraceProperty =
>>> System.getProperty("gshell.show.stacktrace");
>>>          boolean stackTraceFlag = false;
>>>          if (stackTraceProperty != null) {
>>>              stackTraceFlag =  
>>> stackTraceProperty.trim().equals("true");
>>>          }
>>>
>>>          if (io.isDebug()) {
>>>              // If we have debug enabled then skip the fancy bits
>>> below, and log the full error, don't decode shit
>>>              log.debug(error.toString(), error);
>>>          }
>>>          else if (io.isVerbose() || stackTraceFlag) {
>>>              // Render a fancy ansi colored stack trace
>>>              StackTraceElement[] trace = cause.getStackTrace();
>>>              StringBuilder buff = new StringBuilder();
>>>
>>>              //
>>>              // TODO: Move this to helper in gshell-ansi
>>>              //
>>>
>>>              for (StackTraceElement e : trace) {
>>>                  buff.append("        @|bold at| ").
>>>                      append(e.getClassName()).
>>>                      append(".").
>>>                      append(e.getMethodName()).
>>>                      append(" (@|bold ");
>>>
>>>                  buff.append(e.isNativeMethod() ? "Native Method" :
>>>                          (e.getFileName() != null &&
>>> e.getLineNumber() != -1 ? e.getFileName() + ":" +  
>>> e.getLineNumber() :
>>>                              (e.getFileName() != null ?
>>> e.getFileName() : "Unknown Source")));
>>>
>>>                  buff.append("|)");
>>>
>>>                  //
>>>                  // FIXME: This does not properly display the full
>>> exception detail when cause contains nested exceptions
>>>                  //
>>>
>>>                  io.err.println(buff);
>>>
>>>                  buff.setLength(0);
>>>              }
>>>          }
>>>          io.err.flush();
>>>      }
>>>  }
>>>
>>> }
>>>
>>>
>>> On Tue, Nov 11, 2008 at 8:07 AM, Jason Dillon <jason.dillon@gmail.com 
>>> >
>>> wrote:
>>>>
>>>> How does one hook up GShell to use this stuff?
>>>>
>>>> --jason
>>>>
>>>>
>>>> On Nov 7, 2008, at 4:22 AM, Guillaume Nodet wrote:
>>>>
>>>>> Over the past days, I've been working on a implementing a SSH  
>>>>> server
>>>>> in java to replace to gshell remoting bits.
>>>>> The project is currently hosted at google code:
>>>>> http://code.google.com/p/sshd/
>>>>>
>>>>> This project is based on Mina and the current status is that the  
>>>>> ssh
>>>>> protocol is in a working state, but there are still a lots of  
>>>>> things
>>>>> to iron.
>>>>> I've been able to connect using openssh 5.0 and 5.1 and also jsch
>>>>> (from which i borrowed from code btw) and launch an /bin/sh  
>>>>> shell and
>>>>> issue a few commands.
>>>>> I'd be happy if any committer is interested to work on that to  
>>>>> give
>>>>> him commits rights on the project.
>>>>>
>>>>> --
>>>>> Cheers,
>>>>> Guillaume Nodet
>>>>> ------------------------
>>>>> Blog: http://gnodet.blogspot.com/
>>>>> ------------------------
>>>>> Open Source SOA
>>>>> http://fusesource.com
>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Cheers,
>>> Guillaume Nodet
>>> ------------------------
>>> Blog: http://gnodet.blogspot.com/
>>> ------------------------
>>> Open Source SOA
>>> http://fusesource.com
>>
>>
>
>
>
> -- 
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com


Mime
View raw message