diff --git a/core/bbs.js b/core/bbs.js index ab3a1a9c..5f4c006c 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -175,7 +175,7 @@ function startListening() { var port = parseInt(module.runtime.config.port); if(isNaN(port)) { - logger.log.error({ port : module.runtime.config.port, server : module.moduleInfo.name }, 'Cannot load server (Invalid port)'); + logger.log.error( { port : module.runtime.config.port, server : module.moduleInfo.name }, 'Cannot load server (Invalid port)'); return; } @@ -188,11 +188,13 @@ function startListening() { // // Start tracking the client. We'll assign it an ID which is // just the index in our connections array. - // + // if(_.isUndefined(client.session)) { client.session = {}; } + client.session.serverType = moduleInst.getServerType(); + clientConns.addNewClient(client, clientSock); client.on('ready', function onClientReady() { diff --git a/core/client.js b/core/client.js index 6fd43744..29965b89 100644 --- a/core/client.js +++ b/core/client.js @@ -425,7 +425,15 @@ Client.prototype.end = function () { clearInterval(this.idleCheck); - return this.output.end.apply(this.output, arguments); + try { + // + // We can end up calling 'end' before TTY/etc. is established, e.g. with SSH + // + // :TODO: is this OK? + return this.output.end.apply(this.output, arguments); + } catch(e) { + // TypeError + } }; Client.prototype.destroy = function () { diff --git a/core/client_connections.js b/core/client_connections.js index 7a620a78..0caea71e 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -20,7 +20,10 @@ function addNewClient(client, clientSock) { // Create a client specific logger client.log = logger.log.child( { clientId : id } ); - var connInfo = { ip : clientSock.remoteAddress }; + var connInfo = { + ip : clientSock.remoteAddress, + serverType : client.session.serverType, + }; if(client.log.debug()) { connInfo.port = clientSock.localPort; diff --git a/core/client_term.js b/core/client_term.js index 179d83f1..c1c26b6e 100644 --- a/core/client_term.js +++ b/core/client_term.js @@ -74,6 +74,17 @@ function ClientTerminal(output) { // SCREEN // * ConnectBot // + // syncterm + // * + // + // Reports from various terminals + // SyncTERM + // * syncterm + // + // PuTTY + // * xterm + // + // if(this.isANSI()) { this.outputEncoding = 'cp437'; } else { @@ -125,7 +136,7 @@ function ClientTerminal(output) { ClientTerminal.prototype.isANSI = function() { // :TODO: Others?? - return [ 'ansi', 'pc-ansi', 'qansi', 'scoansi' ].indexOf(this.termType) > -1; + return [ 'ansi', 'pc-ansi', 'qansi', 'scoansi', 'syncterm' ].indexOf(this.termType) > -1; }; // :TODO: probably need to update these to convert IAC (0xff) -> IACIAC (escape it) diff --git a/core/config.js b/core/config.js index a3bd36e3..c9d7e96c 100644 --- a/core/config.js +++ b/core/config.js @@ -61,6 +61,8 @@ function getDefaultConfig() { return { general : { boardName : 'Another Fine ENiGMA½ BBS', + + loginAttempts : 3, }, firstMenu : 'connected', diff --git a/core/predefined_mci.js b/core/predefined_mci.js index 0771f461..bf7bf544 100644 --- a/core/predefined_mci.js +++ b/core/predefined_mci.js @@ -54,6 +54,7 @@ function getPredefinedMCIValue(client, code) { UC : function loginCount() { return client.user.properties.login_count.toString(); }, ND : function connectedNode() { return client.node.toString(); }, IP : function clientIpAddress() { return client.address().address; }, + ST : function serverType() { return client.session.serverType; }, MS : function accountCreated() { return moment(client.user.properties.account_created).format(client.currentTheme.helpers.getDateFormat()); }, CS : function currentStatus() { return client.currentStatus; }, diff --git a/core/server_module.js b/core/server_module.js index f4e6a8b5..040beb19 100644 --- a/core/server_module.js +++ b/core/server_module.js @@ -1,7 +1,7 @@ /* jslint node: true */ 'use strict'; -var PluginModule = require('./plugin_module.js').PluginModule; +var PluginModule = require('./plugin_module.js').PluginModule; exports.ServerModule = ServerModule; @@ -12,5 +12,7 @@ function ServerModule() { require('util').inherits(ServerModule, PluginModule); ServerModule.prototype.createServer = function() { - return null; -}; \ No newline at end of file +}; + +ServerModule.prototype.getServerType = function() { +}; diff --git a/core/servers/ssh.js b/core/servers/ssh.js index 6d525cb6..bf549374 100644 --- a/core/servers/ssh.js +++ b/core/servers/ssh.js @@ -40,54 +40,68 @@ function SSHClient(clientConn) { var self = this; + var loginAttempts = 0; + clientConn.on('authentication', function authAttempt(ctx) { self.log.trace( { method : ctx.method, username : ctx.username }, 'SSH authentication attempt'); var username = ctx.username || ''; var password = ctx.password || ''; - if(0 === username.length > 0 && password.length > 0) { + function termConnection() { + ctx.reject(); + clientConn.end(); + } + + if(username.length > 0 && password.length > 0) { + loginAttempts += 1; + userLogin(self, ctx.username, ctx.password, function authResult(err) { if(err) { if(err.existingConn) { // :TODO: Can we display somthing here? - ctx.reject(); - clientConn.end(); + termConnection(); return; } } else { ctx.accept(); } }); - } + } else { + if(-1 === SSHClient.ValidAuthMethods.indexOf(ctx.method)) { + return ctx.reject(SSHClient.ValidAuthMethods); + } - if('keyboard-interactive' !== ctx.method) { - return ctx.reject( ['keyboard-interactive'] ); - } + if(0 === username.length) { + // :TODO: can we display something here? + return ctx.reject(); + } - if(0 === username.length) { - // :TODO: can we display something here? - return ctx.reject(); - } + var interactivePrompt = { prompt: ctx.username + '\'s password: ', echo : false }; - var interactivePrompt = { prompt: ctx.username + '\'s password: ', echo : false }; + ctx.prompt(interactivePrompt, function retryPrompt(answers) { + loginAttempts += 1; - ctx.prompt(interactivePrompt, function retryPrompt(answers) { - userLogin(self, username, (answers[0] || ''), function authResult(err) { - if(err) { - if(err.existingConn) { - // :TODO: can we display something here? - ctx.reject(); - clientConn.end(); + userLogin(self, username, (answers[0] || ''), function authResult(err) { + if(err) { + if(err.existingConn) { + // :TODO: can we display something here? + termConnection(); + } else { + interactivePrompt.prompt = 'Access denied\n' + ctx.username + '\'s password: '; + + if(loginAttempts >= conf.config.general.loginAttempts) { + termConnection(); + } else { + return ctx.prompt(interactivePrompt, retryPrompt); + } + } } else { - interactivePrompt.prompt = 'Access denied\n' + interactivePrompt.prompt; - return ctx.prompt(interactivePrompt, retryPrompt); + ctx.accept(); } - } else { - ctx.accept(); - } - }); - }); + }); + }); + } }); this.updateTermInfo = function(info) { @@ -125,14 +139,16 @@ function SSHClient(clientConn) { clientConn.once('ready', function clientReady() { self.log.info('SSH authentication success'); - clientConn.once('session', function sess(accept, reject) { + clientConn.on('session', function sess(accept, reject) { var session = accept(); - session.once('pty', function pty(accept, reject, info) { + session.on('pty', function pty(accept, reject, info) { self.log.debug(info, 'SSH pty event'); - accept(); + if(_.isFunction(accept)) { + accept(); + } if(self.input) { // do we have I/O? self.updateTermInfo(info); @@ -141,7 +157,7 @@ function SSHClient(clientConn) { } }); - session.once('shell', function shell(accept, reject) { + session.on('shell', function shell(accept, reject) { self.log.debug('SSH shell event'); var channel = accept(); @@ -164,6 +180,8 @@ function SSHClient(clientConn) { session.on('window-change', function windowChange(accept, reject, info) { self.log.debug(info, 'SSH window-change event'); + console.log('window-change: ' + accept) + self.updateTermInfo(info); }); @@ -175,13 +193,14 @@ function SSHClient(clientConn) { }); clientConn.on('error', function connError(err) { - // :TODO: what to do here? - console.log(err) + self.log.warn( { error : err.toString(), code : err.code }, 'SSH connection error'); }); } util.inherits(SSHClient, baseClient.Client); +SSHClient.ValidAuthMethods = [ 'password', 'keyboard-interactive' ]; + function SSHServerModule() { ServerModule.call(this); } @@ -212,4 +231,8 @@ SSHServerModule.prototype.createServer = function() { }); return server; +}; + +SSHServerModule.prototype.getServerType = function() { + return 'SSH'; }; \ No newline at end of file diff --git a/core/servers/telnet.js b/core/servers/telnet.js index ec141c5e..487879e1 100644 --- a/core/servers/telnet.js +++ b/core/servers/telnet.js @@ -784,4 +784,8 @@ TelnetServerModule.prototype.createServer = function() { }); return server; -}; \ No newline at end of file +}; + +TelnetServerModule.prototype.getServerType = function() { + return 'TELNET'; +}; diff --git a/mods/last_callers_old.js b/mods/last_callers_old.js index a25cdd63..30be0811 100644 --- a/mods/last_callers_old.js +++ b/mods/last_callers_old.js @@ -5,7 +5,7 @@ var MenuModule = require('../core/menu_module.js').MenuModule; var userDb = require('../core/database.js').dbs.user; var ViewController = require('../core/view_controller.js').ViewController; var TextView = require('../core/text_view.js').TextView; -var getUserLoginHistory = require('../core/stats.js').getUserLoginHistory; +var getSystemLoginHistory = require('../core/stats.js').getSystemLoginHistory; var util = require('util'); var moment = require('moment'); @@ -92,7 +92,7 @@ LastCallersModule.prototype.mciReady = function(mciData, cb) { }); }, function fetchHistory(callback) { - getUserLoginHistory(self.rows, function historyRetrieved(err, lh) { + getSystemLoginHistory(self.rows, function historyRetrieved(err, lh) { loginHistory = lh; callback(err); }); diff --git a/mods/themes/luciano_blocktronics/STATUS.ANS b/mods/themes/luciano_blocktronics/STATUS.ANS index fd945a26..33bc53e5 100644 Binary files a/mods/themes/luciano_blocktronics/STATUS.ANS and b/mods/themes/luciano_blocktronics/STATUS.ANS differ diff --git a/mods/themes/luciano_blocktronics/theme.hjson b/mods/themes/luciano_blocktronics/theme.hjson index 06b212c0..041b6611 100644 --- a/mods/themes/luciano_blocktronics/theme.hjson +++ b/mods/themes/luciano_blocktronics/theme.hjson @@ -75,6 +75,7 @@ UG5: { width: 17 } UT6: { width: 17 } UC7: { width: 17 } + ST8: { width: 17 } } } @@ -233,6 +234,7 @@ UG5: { width: 17 } UT6: { width: 17 } UC7: { width: 17 } + ST8: { width: 17 } } } }