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
|