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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> >> 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