From 0f1fe31fe536e7a5bc0f6378855438b28294548e Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Tue, 20 Oct 2015 15:39:33 -0600 Subject: [PATCH] * SSH semi functional --- core/bbs.js | 4 ++-- core/client.js | 22 +++++++++++++----- core/client_connections.js | 8 +++---- core/servers/ssh.js | 46 +++++++++++++++++++++++--------------- core/servers/telnet.js | 19 +++------------- 5 files changed, 53 insertions(+), 46 deletions(-) diff --git a/core/bbs.js b/core/bbs.js index c7973973..08109af2 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -184,7 +184,7 @@ function startListening() { // :TODO: handle maxConnections, e.g. conf.maxConnections - server.on('client', function onClient(client) { + server.on('client', function newClient(client, clientSock) { // // Start tracking the client. We'll assign it an ID which is // just the index in our connections array. @@ -193,7 +193,7 @@ function startListening() { client.session = {}; } - clientConns.addNewClient(client); + clientConns.addNewClient(client, clientSock); client.on('ready', function onClientReady() { diff --git a/core/client.js b/core/client.js index 70695b95..b9f48881 100644 --- a/core/client.js +++ b/core/client.js @@ -5,8 +5,9 @@ Portions of this code for key handling heavily inspired from the following: https://github.com/chjj/blessed/blob/master/lib/keys.js - MIT license is as follows: - -------------------------- + chji's blessed is MIT licensed: + + ----/snip/---------------------- The MIT License (MIT) Copyright (c) @@ -28,7 +29,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------- + ----/snip/---------------------- */ var term = require('./client_term.js'); var miscUtil = require('./misc_util.js'); @@ -86,9 +87,9 @@ function Client(input, output) { var self = this; - this.input = input; - this.output = output; - this.term = new term.ClientTerminal(this.output); + //this.input = input; + //this.output = output; + //this.term = new term.ClientTerminal(this.output); this.user = new user.User(); this.currentTheme = { info : { name : 'N/A', description : 'None' } }; this.lastKeyPressMs = Date.now(); @@ -110,6 +111,8 @@ function Client(input, output) { } }); + + // // Peek at incoming |data| and emit events for any special // handling that may include: @@ -398,6 +401,13 @@ function Client(input, output) { require('util').inherits(Client, stream); +Client.prototype.setInputOutput = function(input, output) { + this.input = input; + this.output = output; + + this.term = new term.ClientTerminal(this.output); +}; + Client.prototype.end = function () { this.detachCurrentMenuModule(); diff --git a/core/client_connections.js b/core/client_connections.js index ae099a9b..7a620a78 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -14,17 +14,17 @@ function getActiveConnections() { return clientConnections.length; } -function addNewClient(client) { +function addNewClient(client, clientSock) { var id = client.session.id = clientConnections.push(client) - 1; // Create a client specific logger client.log = logger.log.child( { clientId : id } ); - var connInfo = { ip : client.input.remoteAddress }; + var connInfo = { ip : clientSock.remoteAddress }; if(client.log.debug()) { - connInfo.port = client.input.localPort; - connInfo.family = client.input.localFamily; + connInfo.port = clientSock.localPort; + connInfo.family = clientSock.localFamily; } client.log.info(connInfo, 'Client connected'); diff --git a/core/servers/ssh.js b/core/servers/ssh.js index 9a88aa84..da739984 100644 --- a/core/servers/ssh.js +++ b/core/servers/ssh.js @@ -7,11 +7,7 @@ var baseClient = require('../client.js'); var Log = require('../logger.js').log; var ServerModule = require('../server_module.js').ServerModule; var userLogin = require('../user_login.js').userLogin; - -// :TODO: remove this - currently an experimental hack: -var term = require('../client_term.js'); - -var packageJson = require('../../package.json'); +var enigVersion = require('../../package.json').version; var ssh2 = require('ssh2'); var fs = require('fs'); @@ -26,6 +22,26 @@ exports.moduleInfo = { exports.getModule = SSHServerModule; +/* +Hello, + +If you follow the first server example in the `ssh2` readme and substitute the `session.once('exec', ...)` with `session.once('shell', ...)` +you should be fine. Just about all ssh clients default to an interactive shell session so that is what you will want to look for. As the +documentation notes, the `shell` event handler is just passed `accept, reject` with `accept()` returning a duplex stream representing +stdin/stdout. You can write to stderr by using the `stderr` property of the duplex stream object. + +You will probably also want to handle the `pty` event on the session, since most clients (by default) will request a pseudo-TTY before +requesting an interactive shell. I believe this event may be especially useful in your case because the ssh client can send certain terminal +modes which can have relevance with your telnet usage. The event info also contains window dimensions which may help in determining layout +of your display (there is also a `window-change` event that contains these same dimensions whenever the client's screen/window dimensions +change). + +If you are still having problems after making these changes, post your code somewhere and I will see if there is anything out of place. +Additionally, you can set `debug: console.log` in the server config object to show debug output which may be useful to see what is or isn't +being sent/received ssh protocol-wise. +*/ + + function SSHClient(clientConn) { baseClient.Client.apply(this, arguments); @@ -106,7 +122,7 @@ function SSHClient(clientConn) { var session = accept(); - session.on('pty-req', function pty(accept, reject, info) { + session.on('pty', function pty(accept, reject, info) { console.log(info); var channel = accept(); console.log(channel) @@ -116,13 +132,7 @@ function SSHClient(clientConn) { session.on('shell', function shell(accept, reject) { var channel = accept(); - channel._write('Hello, world!') - - self.input = channel._client._sock; - self.output = channel._client._sock; - - - self.term = new term.ClientTerminal(self.output); + self.setInputOutput(channel.stdin, channel.stdout); self.emit('ready') }); @@ -146,14 +156,13 @@ util.inherits(SSHServerModule, ServerModule); SSHServerModule.prototype.createServer = function() { SSHServerModule.super_.prototype.createServer.call(this); - // :TODO: setup all options here. What should the banner, etc. really be???? var serverConf = { privateKey : fs.readFileSync(conf.config.servers.ssh.rsaPrivateKey), - banner : 'ENiGMA½ BBS ' + packageJson.version + ' SSH Server', - ident : 'enigma-bbs-' + packageJson.version + '-srv', + banner : 'ENiGMA½ BBS ' + enigVersion + ' SSH Server', + ident : 'enigma-bbs-' + enigVersion + '-srv', debug : function debugSsh(dbgLine) { if(true === conf.config.servers.ssh.debugConnections) { - self.log.trace('SSH: ' + dbgLine); + Log.trace('SSH: ' + dbgLine); } }, }; @@ -163,7 +172,8 @@ SSHServerModule.prototype.createServer = function() { Log.info(info, 'New SSH connection'); var client = new SSHClient(conn); - this.emit('client', client); + + this.emit('client', client, conn._sock); }); return server; diff --git a/core/servers/telnet.js b/core/servers/telnet.js index ba68df4c..9e5ac94e 100644 --- a/core/servers/telnet.js +++ b/core/servers/telnet.js @@ -430,6 +430,8 @@ function TelnetClient(input, output) { var readyFired = false; var encodingSet = false; + this.setInputOutput(input, output); + this.negotiationsComplete = false; // are we in the 'negotiation' phase? this.didReady = false; // have we emit the 'ready' event? @@ -761,21 +763,6 @@ Object.keys(OPTIONS).forEach(function(name) { }); }); -/* -function createServer() { - var server = net.createServer(function onConnection(sock) { - var self = this; - var client = new TelnetClient(sock, sock); - - client.banner(); - - self.emit('client', client); - }); - - return server; -} -*/ - function TelnetServerModule() { ServerModule.call(this); } @@ -791,7 +778,7 @@ TelnetServerModule.prototype.createServer = function() { client.banner(); - self.emit('client', client); + self.emit('client', client, sock); }); return server;