Return-Path: Delivered-To: apmail-geronimo-dev-archive@www.apache.org Received: (qmail 46916 invoked from network); 22 Nov 2008 06:03:57 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 22 Nov 2008 06:03:57 -0000 Received: (qmail 12229 invoked by uid 500); 22 Nov 2008 06:04:05 -0000 Delivered-To: apmail-geronimo-dev-archive@geronimo.apache.org Received: (qmail 12167 invoked by uid 500); 22 Nov 2008 06:04:05 -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 12151 invoked by uid 99); 22 Nov 2008 06:04:05 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Nov 2008 22:04:05 -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.142.186 as permitted sender) Received: from [209.85.142.186] (HELO ti-out-0910.google.com) (209.85.142.186) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 22 Nov 2008 06:02:38 +0000 Received: by ti-out-0910.google.com with SMTP id b6so732362tic.1 for ; Fri, 21 Nov 2008 22:03:22 -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=3yro54cpAAz4LWOoMqucg3/Sgn5jsFkp/CUgGaQIMRo=; b=vQHqlt0Z+JxAn5HRmL54ZBX0hAsiXkRX0qHHiOznsqPdjap/rG03OjwaCSyuf448fR nKR8wY4t5qm7B0gEr3UtkQBQ2R4nQ/RZrzO/pxtWKdAiW2MF9wXUBw+5aQ2Gl79fyerk NlB1QjDssxjrBWhG8I6bhzPwFoKG3cXJ/DBb0= 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=w+aGXZtnfpEdm3KTUJJFm52B2uWC+7yT7cT+RVQ5T60MynzIUzCS1Sp/a9ubVXuhpL 0GCEBCCmmT/ufSHcR1Aqhdqj5NeiKu3l+9/XoJfhp062l0DuzDks+0jRepnTRbLu0th7 SsyvrDx2ZU+dhiWssFTx1ac1EEty8fjGEIic8= Received: by 10.110.86.3 with SMTP id j3mr1728056tib.24.1227333802314; Fri, 21 Nov 2008 22:03:22 -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 y3sm3459276tia.6.2008.11.21.22.03.18 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 21 Nov 2008 22:03:20 -0800 (PST) Cc: dev@openejb.apache.org, dev@geronimo.apache.org, dev@servicemix.apache.org, "Jason Dillon" Message-Id: 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: Sat, 22 Nov 2008 13:03:16 +0700 References: <5F573FE2-6E08-44FF-B08A-094BF5CEFBA3@gmail.com> <9E831EED-F156-4162-BC8A-B8DFDB453B30@gmail.com> X-Mailer: Apple Mail (2.929.2) X-Virus-Checked: Checked by ClamAV on apache.org 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 > 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; >>> } >>> } >>> >>> >>> ================================================== >>> >> 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.cipher.BlowfishCBC$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 >> >> > > > > -- > Cheers, > Guillaume Nodet > ------------------------ > Blog: http://gnodet.blogspot.com/ > ------------------------ > Open Source SOA > http://fusesource.com