You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@servicemix.apache.org by Guillaume Nodet <gn...@gmail.com> on 2008/11/06 22:22:58 UTC

[Heads up] SSH server in java

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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, a vote is already going on to start the SSH subproject.

On Sun, Nov 23, 2008 at 8:19 AM, Jason Dillon <ja...@gmail.com> wrote:
> On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
>>>
>>> <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.
>
> I will investigate more... I did not see the exception spat out on the
> client when entering a bad command... perhaps that is because of the above
> msgs?
>
>> 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.
>
> Have you talked to the mina folks about it?  Anyways, I can't stop saying
> how thrilled I am about this.  You rock!  Needless to say next time we meet
> up I'm gonna buy you all the beer you can drink ;-)
>
> --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 <ja...@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
>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
>> <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.

I will investigate more... I did not see the exception spat out on the  
client when entering a bad command... perhaps that is because of the  
above msgs?

> 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.

Have you talked to the mina folks about it?  Anyways, I can't stop  
saying how thrilled I am about this.  You rock!  Needless to say next  
time we meet up I'm gonna buy you all the beer you can drink ;-)

--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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
> On Sat, Nov 22, 2008 at 7:32 AM, Jason Dillon  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
>> <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.

I will investigate more... I did not see the exception spat out on the  
client when entering a bad command... perhaps that is because of the  
above msgs?

> 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.

Have you talked to the mina folks about it?  Anyways, I can't stop  
saying how thrilled I am about this.  You rock!  Needless to say next  
time we meet up I'm gonna buy you all the beer you can drink ;-)

--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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote:
> On Sat, Nov 22, 2008 at 7:32 AM, Jason Dillon  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
On Sat, Nov 22, 2008 at 7:32 AM, Jason Dillon <ja...@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.

> 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.

> 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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
On Sat, Nov 22, 2008 at 7:32 AM, Jason Dillon <ja...@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.

> 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.

> 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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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.

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.

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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Fricken awesome!  I'd be more than happy to make the gshell remoting  
stuff go away in favor of using ssh ;-)  I will take a closer look at  
this in the next day or so.  I'm very excited by this work!

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Your limited is my "kick-ass amazing" :-P

--jason


On Nov 22, 2008, at 6:45 PM, Guillaume Nodet wrote:

> Yes, i've refactored things a bit in the sshd project to make room for
> the client side.
> It's really limited for now and only support user/password
> authentication and launching a shell.
> I've implemented a gshell action at [1] for the client:
>
> [1] https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshAction.java
>
> On Sat, Nov 22, 2008 at 7:03 AM, Jason Dillon  
> <ja...@gmail.com> wrote:
>> Cool, I'm going to start a gshell-ssh module under gshell-commands  
>> for the
>> sshd and ssh commands, which will replace the gshell-remote bits :-)
>>
>> I noticed you got some client goo in there too... how is that  
>> working?
>>
>> --jason
>>
>>
>> On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:
>>
>>> Yes, I've checked that in yesterday or so:
>>>
>>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
>>>
>>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>>>
>>>
>>> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <jason.dillon@gmail.com 
>>> >
>>> wrote:
>>>>
>>>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
>>>> checked
>>>> in
>>>> somewhere?
>>>>
>>>> --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
>>
>>
>
>
>
> -- 
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Your limited is my "kick-ass amazing" :-P

--jason


On Nov 22, 2008, at 6:45 PM, Guillaume Nodet wrote:

> Yes, i've refactored things a bit in the sshd project to make room for
> the client side.
> It's really limited for now and only support user/password
> authentication and launching a shell.
> I've implemented a gshell action at [1] for the client:
>
> [1] https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshAction.java
>
> On Sat, Nov 22, 2008 at 7:03 AM, Jason Dillon  
> <ja...@gmail.com> wrote:
>> Cool, I'm going to start a gshell-ssh module under gshell-commands  
>> for the
>> sshd and ssh commands, which will replace the gshell-remote bits :-)
>>
>> I noticed you got some client goo in there too... how is that  
>> working?
>>
>> --jason
>>
>>
>> On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:
>>
>>> Yes, I've checked that in yesterday or so:
>>>
>>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
>>>
>>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>>>
>>>
>>> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <jason.dillon@gmail.com 
>>> >
>>> wrote:
>>>>
>>>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
>>>> checked
>>>> in
>>>> somewhere?
>>>>
>>>> --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
>>
>>
>
>
>
> -- 
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com


Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, i've refactored things a bit in the sshd project to make room for
the client side.
It's really limited for now and only support user/password
authentication and launching a shell.
I've implemented a gshell action at [1] for the client:

[1] https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshAction.java

On Sat, Nov 22, 2008 at 7:03 AM, Jason Dillon <ja...@gmail.com> wrote:
> Cool, I'm going to start a gshell-ssh module under gshell-commands for the
> sshd and ssh commands, which will replace the gshell-remote bits :-)
>
> I noticed you got some client goo in there too... how is that working?
>
> --jason
>
>
> On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:
>
>> Yes, I've checked that in yesterday or so:
>>
>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
>>
>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>>
>>
>> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <ja...@gmail.com>
>> wrote:
>>>
>>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd" checked
>>> in
>>> somewhere?
>>>
>>> --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 <ja...@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
>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, i've refactored things a bit in the sshd project to make room for
the client side.
It's really limited for now and only support user/password
authentication and launching a shell.
I've implemented a gshell action at [1] for the client:

[1] https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshAction.java

On Sat, Nov 22, 2008 at 7:03 AM, Jason Dillon <ja...@gmail.com> wrote:
> Cool, I'm going to start a gshell-ssh module under gshell-commands for the
> sshd and ssh commands, which will replace the gshell-remote bits :-)
>
> I noticed you got some client goo in there too... how is that working?
>
> --jason
>
>
> On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:
>
>> Yes, I've checked that in yesterday or so:
>>
>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
>>
>> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>>
>>
>> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <ja...@gmail.com>
>> wrote:
>>>
>>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd" checked
>>> in
>>> somewhere?
>>>
>>> --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 <ja...@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
>
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Cool, I'm going to start a gshell-ssh module under gshell-commands for  
the sshd and ssh commands, which will replace the gshell-remote bits :-)

I noticed you got some client goo in there too... how is that working?

--jason


On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:

> Yes, I've checked that in yesterday or so:
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>
>
> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon  
> <ja...@gmail.com> wrote:
>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
>> checked in
>> somewhere?
>>
>> --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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Cool, I'm going to start a gshell-ssh module under gshell-commands for  
the sshd and ssh commands, which will replace the gshell-remote bits :-)

I noticed you got some client goo in there too... how is that working?

--jason


On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:

> Yes, I've checked that in yesterday or so:
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>
>
> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon  
> <ja...@gmail.com> wrote:
>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
>> checked in
>> somewhere?
>>
>> --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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Cool, I'm going to start a gshell-ssh module under gshell-commands for  
the sshd and ssh commands, which will replace the gshell-remote bits :-)

I noticed you got some client goo in there too... how is that working?

--jason


On Nov 21, 2008, at 3:29 PM, Guillaume Nodet wrote:

> Yes, I've checked that in yesterday or so:
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
> https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
>
>
> On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon  
> <ja...@gmail.com> wrote:
>> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
>> checked in
>> somewhere?
>>
>> --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


Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, I've checked that in yesterday or so:
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml


On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <ja...@gmail.com> wrote:
> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd" checked in
> somewhere?
>
> --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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, I've checked that in yesterday or so:
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml


On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <ja...@gmail.com> wrote:
> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd" checked in
> somewhere?
>
> --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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
Yes, I've checked that in yesterday or so:
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/
 https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml


On Fri, Nov 21, 2008 at 7:08 AM, Jason Dillon <ja...@gmail.com> wrote:
> Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd" checked in
> somewhere?
>
> --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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
checked in somewhere?

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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.

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.

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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
checked in somewhere?

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Hey, do you have "org.apache.servicemix.kernel.gshell.core.sshd"  
checked in somewhere?

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Fricken awesome!  I'd be more than happy to make the gshell remoting  
stuff go away in favor of using ssh ;-)  I will take a closer look at  
this in the next day or so.  I'm very excited by this work!

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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.

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.

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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
Fricken awesome!  I'd be more than happy to make the gshell remoting  
stuff go away in favor of using ssh ;-)  I will take a closer look at  
this in the next day or so.  I'm very excited by this work!

--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  
> <ja...@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


Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Guillaume Nodet <gn...@gmail.com>.
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 <ja...@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

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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


Re: [Heads up] SSH server in java

Posted by Chris Custine <cc...@apache.org>.
Wow...  Just getting around to looking at this.  Nice work.

Chris

--
Chris Custine
My Blog :: http://blog.organicelement.com
Apache ServiceMix :: http://servicemix.apache.org
Apache Directory Server :: http://directory.apache.org


On Thu, Nov 6, 2008 at 2:22 PM, Guillaume Nodet <gn...@gmail.com> 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
>

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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


Re: [Heads up] SSH server in java

Posted by Chris Custine <cc...@apache.org>.
Wow...  Just getting around to looking at this.  Nice work.

Chris

--
Chris Custine
My Blog :: http://blog.organicelement.com
Apache ServiceMix :: http://servicemix.apache.org
Apache Directory Server :: http://directory.apache.org


On Thu, Nov 6, 2008 at 2:22 PM, Guillaume Nodet <gn...@gmail.com> 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
>

Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
This is fricken awesome!

--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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
This is fricken awesome!

--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


Re: [Heads up] SSH server in java

Posted by Jason Dillon <ja...@gmail.com>.
This is fricken awesome!

--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