Return-Path: Delivered-To: apmail-geronimo-dev-archive@www.apache.org Received: (qmail 47290 invoked from network); 21 Nov 2008 06:08:58 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 21 Nov 2008 06:08:58 -0000 Received: (qmail 54270 invoked by uid 500); 21 Nov 2008 06:09:06 -0000 Delivered-To: apmail-geronimo-dev-archive@geronimo.apache.org Received: (qmail 54228 invoked by uid 500); 21 Nov 2008 06:09:06 -0000 Mailing-List: contact dev-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list dev@geronimo.apache.org Received: (qmail 54217 invoked by uid 99); 21 Nov 2008 06:09:06 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Nov 2008 22:09:06 -0800 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of jason.dillon@gmail.com designates 209.85.198.232 as permitted sender) Received: from [209.85.198.232] (HELO rv-out-0506.google.com) (209.85.198.232) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Nov 2008 06:07:40 +0000 Received: by rv-out-0506.google.com with SMTP id f6so791090rvb.55 for ; Thu, 20 Nov 2008 22:08:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:cc:message-id:from:to :in-reply-to:content-type:content-transfer-encoding:mime-version :subject:date:references:x-mailer; bh=BGFBFJFdF8Zgalr3HxZWxIM2W6o5usub39qXDEOcJTs=; b=PBYdp1H5/mBkUwRW/bwH2nZheL7QNo3KbYqPpQSIZWI5mWAygMpxn2bS6HnQOXNhbh 8ks45oRNt5VDxJAA0/m2WSODTGNQA69qQPg1MewjjybYO4+yTAiQMThLFizhcS3H7zvG SRNWRYsqJjVWtLNneyScvsxvMPXoXNoEqb0DI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=cc:message-id:from:to:in-reply-to:content-type :content-transfer-encoding:mime-version:subject:date:references :x-mailer; b=EqtgWWnwaHp0jdibbZmbxtixmuxEiIjoJQabNpE9DSvkuNYwmMEz1QGDWZrgctIXmn mTWboKwCQ3hmrLm/RT2n5nzNJQf7nhodg2EhPIk8UGr6GqnadamI3fZfUQ7IE23X0k38 Jw+si018oOj8+vvCLHZ+h7C9OO+YtcVCP3GV4= Received: by 10.142.255.14 with SMTP id c14mr104066wfi.138.1227247704852; Thu, 20 Nov 2008 22:08:24 -0800 (PST) Received: from ?10.0.1.100? (ppp-58-8-3-104.revip2.asianet.co.th [58.8.3.104]) by mx.google.com with ESMTPS id 31sm2488619wff.23.2008.11.20.22.08.20 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 20 Nov 2008 22:08:23 -0800 (PST) Cc: dev@openejb.apache.org, dev@geronimo.apache.org, dev@servicemix.apache.org, "Jason Dillon" Message-Id: <9E831EED-F156-4162-BC8A-B8DFDB453B30@gmail.com> From: Jason Dillon To: Guillaume Nodet In-Reply-To: Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v929.2) Subject: Re: [Heads up] SSH server in java Date: Fri, 21 Nov 2008 13:08:15 +0700 References: <5F573FE2-6E08-44FF-B08A-094BF5CEFBA3@gmail.com> X-Mailer: Apple Mail (2.929.2) X-Virus-Checked: Checked by ClamAV on apache.org 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; > } > } > > > ================================================== > init-method="start" destroy-method="stop"> > > > class > ="org.apache.servicemix.kernel.gshell.core.sshd.GShellShellFactory"> > > > > > > > > > > class="org.apache.geronimo.gshell.wisdom.shell.HistoryImpl"> > > > > > class="org.apache.geronimo.gshell.wisdom.shell.ConsolePrompterImpl"> > > > > > > > class="com.google.code.sshd.hostkeys.FileHostKeyProvider"> > > > ${hostKey} > > > > > > > class > = > "org > .apache.servicemix.kernel.gshell.core.sshd.BogusPasswordAuthenticator" > /> > > > > > > class="com.google.code.sshd.channel.ChannelSession$Factory" /> > > > > > > class="com.google.code.sshd.cipher.TripleDESCBC$Factory" /> > > > > > > > > class="com.google.code.sshd.compression.CompressionNone$Factory" /> > > > > > > > > > > class="com.google.code.sshd.mac.HMACMD5$Factory" /> > class="com.google.code.sshd.mac.HMACSHA1$Factory" /> > class="com.google.code.sshd.mac.HMACMD596$Factory" /> > class="com.google.code.sshd.mac.HMACSHA196$Factory" /> > > > > > > > > class="com.google.code.sshd.auth.UserAuthPublicKey$Factory" /> > class="com.google.code.sshd.auth.UserAuthPassword$Factory" /> > > > > > class="com.google.code.sshd.signature.SignatureDSA$Factory" /> > class="com.google.code.sshd.signature.SignatureRSA$Factory" /> > > > > > > > =================================================== > 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 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 getCompleters() { > return completers; > } > > public void setCompleters(List 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 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 > 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