geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jason Dillon <jason.dil...@gmail.com>
Subject Re: [Heads up] SSH server in java
Date Fri, 21 Nov 2008 06:08:15 GMT
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


Mime
View raw message