diff --git a/app/server/socket.js b/app/server/socket.js
index f2767ea1..6ccd64f1 100644
--- a/app/server/socket.js
+++ b/app/server/socket.js
@@ -1,136 +1,172 @@
/* eslint-disable complexity */
-'use strict'
+/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }],
+ no-console: ["error", { allow: ["warn", "error"] }] */
/* jshint esversion: 6, asi: true, node: true */
// socket.js
// private
-var debug = require('debug')
-var debugWebSSH2 = require('debug')('WebSSH2')
-var SSH = require('ssh2').Client
-var CIDRMatcher = require('cidr-matcher')
+const debug = require('debug');
+const debugWebSSH2 = require('debug')('WebSSH2');
+const SSH = require('ssh2').Client;
+const CIDRMatcher = require('cidr-matcher');
// var fs = require('fs')
// var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8'))
-var termCols, termRows
-var menuData = ' Start Log' +
- ' Download Log'
+let termCols;
+let termRows;
+const menuData = ' Start Log'
+ + ' Download Log';
// public
-module.exports = function socket (socket) {
+module.exports = function appSocket(socket) {
// if websocket connection arrives without an express session, kill it
if (!socket.request.session) {
- socket.emit('401 UNAUTHORIZED')
- debugWebSSH2('SOCKET: No Express Session / REJECTED')
- socket.disconnect(true)
- return
+ socket.emit('401 UNAUTHORIZED');
+ debugWebSSH2('SOCKET: No Express Session / REJECTED');
+ socket.disconnect(true);
+ return;
}
+ function SSHerror(myFunc, err) {
+ let theError;
+ if (socket.request.session) {
+ // we just want the first error of the session to pass to the client
+ const firstError = (socket.request.session.error)
+ || ((err) ? err.message : undefined);
+ theError = (firstError) ? `: ${firstError}` : '';
+ // log unsuccessful login attempt
+ if (err && (err.level === 'client-authentication')) {
+ console.error(`WebSSH2 ${'error: Authentication failure'.red.bold
+ } user=${socket.request.session.username.yellow.bold.underline
+ } from=${socket.handshake.address.yellow.bold.underline}`);
+ socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
+ socket.emit('reauth');
+ } else {
+ // eslint-disable-next-line no-console
+ console.log(`WebSSH2 Logout: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`);
+ if (err) {
+ theError = (err) ? `: ${err.message}` : '';
+ console.error(`WebSSH2 error${theError}`);
+ }
+ }
+ socket.emit('ssherror', `SSH ${myFunc}${theError}`);
+ socket.request.session.destroy();
+ socket.disconnect(true);
+ } else {
+ theError = (err) ? `: ${err.message}` : '';
+ socket.disconnect(true);
+ }
+ debugWebSSH2(`SSHerror ${myFunc}${theError}`);
+ }
// If configured, check that requsted host is in a permitted subnet
- if ((((socket.request.session || {}).ssh || {}).allowedSubnets || {}).length && (socket.request.session.ssh.allowedSubnets.length > 0)) {
- var matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets)
+ if ((((socket.request.session || {}).ssh || {}).allowedSubnets || {}).length
+ && (socket.request.session.ssh.allowedSubnets.length > 0)) {
+ const matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets);
if (!matcher.contains(socket.request.session.ssh.host)) {
- console.log('WebSSH2 ' + 'error: Requested host outside configured subnets / REJECTED'.red.bold +
- ' user=' + socket.request.session.username.yellow.bold.underline +
- ' from=' + socket.handshake.address.yellow.bold.underline)
- socket.emit('ssherror', '401 UNAUTHORIZED')
- socket.disconnect(true)
- return
+ console.error(`WebSSH2 ${'error: Requested host outside configured subnets / REJECTED'.red.bold
+ } user=${socket.request.session.username.yellow.bold.underline
+ } from=${socket.handshake.address.yellow.bold.underline}`);
+ socket.emit('ssherror', '401 UNAUTHORIZED');
+ socket.disconnect(true);
+ return;
}
}
- var conn = new SSH()
- socket.on('geometry', function socketOnGeometry (cols, rows) {
- termCols = cols
- termRows = rows
- })
- conn.on('banner', function connOnBanner (data) {
+ const conn = new SSH();
+ socket.on('geometry', (cols, rows) => {
+ termCols = cols;
+ termRows = rows;
+ });
+ conn.on('banner', (data) => {
// need to convert to cr/lf for proper formatting
- data = data.replace(/\r?\n/g, '\r\n')
- socket.emit('data', data.toString('utf-8'))
- })
+ socket.emit('data', data.replace(/\r?\n/g, '\r\n').toString('utf-8'));
+ });
- conn.on('ready', function connOnReady () {
- console.log('WebSSH2 Login: user=' + socket.request.session.username + ' from=' + socket.handshake.address + ' host=' + socket.request.session.ssh.host + ' port=' + socket.request.session.ssh.port + ' sessionID=' + socket.request.sessionID + '/' + socket.id + ' mrhsession=' + socket.request.session.ssh.mrhsession + ' allowreplay=' + socket.request.session.ssh.allowreplay + ' term=' + socket.request.session.ssh.term)
- socket.emit('menu', menuData)
- socket.emit('allowreauth', socket.request.session.ssh.allowreauth)
- socket.emit('setTerminalOpts', socket.request.session.ssh.terminal)
- socket.emit('title', 'ssh://' + socket.request.session.ssh.host)
- if (socket.request.session.ssh.header.background) socket.emit('headerBackground', socket.request.session.ssh.header.background)
- if (socket.request.session.ssh.header.name) socket.emit('header', socket.request.session.ssh.header.name)
- socket.emit('footer', 'ssh://' + socket.request.session.username + '@' + socket.request.session.ssh.host + ':' + socket.request.session.ssh.port)
- socket.emit('status', 'SSH CONNECTION ESTABLISHED')
- socket.emit('statusBackground', 'green')
- socket.emit('allowreplay', socket.request.session.ssh.allowreplay)
+ conn.on('ready', () => {
+ debugWebSSH2(`WebSSH2 Login: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} mrhsession=${socket.request.session.ssh.mrhsession} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`);
+ socket.emit('menu', menuData);
+ socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
+ socket.emit('setTerminalOpts', socket.request.session.ssh.terminal);
+ socket.emit('title', `ssh://${socket.request.session.ssh.host}`);
+ if (socket.request.session.ssh.header.background) socket.emit('headerBackground', socket.request.session.ssh.header.background);
+ if (socket.request.session.ssh.header.name) socket.emit('header', socket.request.session.ssh.header.name);
+ socket.emit('footer', `ssh://${socket.request.session.username}@${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`);
+ socket.emit('status', 'SSH CONNECTION ESTABLISHED');
+ socket.emit('statusBackground', 'green');
+ socket.emit('allowreplay', socket.request.session.ssh.allowreplay);
conn.shell({
term: socket.request.session.ssh.term,
cols: termCols,
- rows: termRows
- }, function connShell (err, stream) {
+ rows: termRows,
+ }, (err, stream) => {
if (err) {
- SSHerror('EXEC ERROR' + err)
- conn.end()
- return
+ SSHerror(`EXEC ERROR${err}`);
+ conn.end();
+ return;
}
// poc to log commands from client
- if (socket.request.session.ssh.serverlog.client) var dataBuffer
- socket.on('data', function socketOnData (data) {
- stream.write(data)
+ // if (socket.request.session.ssh.serverlog.client) var dataBuffer;
+ socket.on('data', (data) => {
+ stream.write(data);
// poc to log commands from client
- if (socket.request.session.ssh.serverlog.client) {
+ /* if (socket.request.session.ssh.serverlog.client) {
if (data === '\r') {
- console.log('serverlog.client: ' + socket.request.session.id + '/' + socket.id + ' host: ' + socket.request.session.ssh.host + ' command: ' + dataBuffer)
- dataBuffer = undefined
+ console.log(`serverlog.client: ${socket.request.session.id}/${socket.id}
+ host: ${socket.request.session.ssh.host} command: ${dataBuffer}`);
+ dataBuffer = undefined;
} else {
- dataBuffer = (dataBuffer) ? dataBuffer + data : data
+ dataBuffer = (dataBuffer) ? dataBuffer + data : data;
}
- }
- })
- socket.on('control', function socketOnControl (controlData) {
+ } */
+ });
+ socket.on('control', (controlData) => {
switch (controlData) {
case 'replayCredentials':
if (socket.request.session.ssh.allowreplay) {
- stream.write(socket.request.session.userpassword + '\n')
+ stream.write(`${socket.request.session.userpassword}\n`);
}
/* falls through */
default:
- console.log('controlData: ' + controlData)
+ debugWebSSH2(`controlData: ${controlData}`);
}
- })
- socket.on('resize', function socketOnResize (data) {
- stream.setWindow(data.rows, data.cols)
- })
- socket.on('disconnecting', function socketOnDisconnecting (reason) { debugWebSSH2('SOCKET DISCONNECTING: ' + reason) })
- socket.on('disconnect', function socketOnDisconnect (reason) {
- debugWebSSH2('SOCKET DISCONNECT: ' + reason)
- err = { message: reason }
- SSHerror('CLIENT SOCKET DISCONNECT', err)
- conn.end()
+ });
+ socket.on('resize', (data) => {
+ stream.setWindow(data.rows, data.cols);
+ });
+ socket.on('disconnecting', (reason) => { debugWebSSH2(`SOCKET DISCONNECTING: ${reason}`); });
+ socket.on('disconnect', (reason) => {
+ debugWebSSH2(`SOCKET DISCONNECT: ${reason}`);
+ const errMsg = { message: reason };
+ SSHerror('CLIENT SOCKET DISCONNECT', errMsg);
+ conn.end();
// socket.request.session.destroy()
- })
- socket.on('error', function socketOnError (err) {
- SSHerror('SOCKET ERROR', err)
- conn.end()
- })
+ });
+ socket.on('error', (errMsg) => {
+ SSHerror('SOCKET ERROR', errMsg);
+ conn.end();
+ });
- stream.on('data', function streamOnData (data) { socket.emit('data', data.toString('utf-8')) })
- stream.on('close', function streamOnClose (code, signal) {
- err = { message: ((code || signal) ? (((code) ? 'CODE: ' + code : '') + ((code && signal) ? ' ' : '') + ((signal) ? 'SIGNAL: ' + signal : '')) : undefined) }
- SSHerror('STREAM CLOSE', err)
- conn.end()
- })
- stream.stderr.on('data', function streamStderrOnData (data) {
- console.log('STDERR: ' + data)
- })
- })
- })
+ stream.on('data', (data) => { socket.emit('data', data.toString('utf-8')); });
+ stream.on('close', (code, signal) => {
+ const errMsg = { message: ((code || signal) ? (((code) ? `CODE: ${code}` : '') + ((code && signal) ? ' ' : '') + ((signal) ? `SIGNAL: ${signal}` : '')) : undefined) };
+ SSHerror('STREAM CLOSE', errMsg);
+ conn.end();
+ });
+ stream.stderr.on('data', (data) => {
+ console.error(`STDERR: ${data}`);
+ });
+ });
+ });
- conn.on('end', function connOnEnd (err) { SSHerror('CONN END BY HOST', err) })
- conn.on('close', function connOnClose (err) { SSHerror('CONN CLOSE', err) })
- conn.on('error', function connOnError (err) { SSHerror('CONN ERROR', err) })
- conn.on('keyboard-interactive', function connOnKeyboardInteractive (name, instructions, instructionsLang, prompts, finish) {
- debugWebSSH2('conn.on(\'keyboard-interactive\')')
- finish([socket.request.session.userpassword])
- })
- if (socket.request.session.username && (socket.request.session.userpassword || socket.request.session.privatekey) && socket.request.session.ssh) {
+ conn.on('end', (err) => { SSHerror('CONN END BY HOST', err); });
+ conn.on('close', (err) => { SSHerror('CONN CLOSE', err); });
+ conn.on('error', (err) => { SSHerror('CONN ERROR', err); });
+ conn.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => {
+ debugWebSSH2('conn.on(\'keyboard-interactive\')');
+ finish([socket.request.session.userpassword]);
+ });
+ if (socket.request.session.username
+ && (socket.request.session.userpassword || socket.request.session.privatekey)
+ && socket.request.session.ssh) {
// console.log('hostkeys: ' + hostkeys[0].[0])
conn.connect({
host: socket.request.session.ssh.host,
@@ -145,13 +181,13 @@ module.exports = function socket (socket) {
readyTimeout: socket.request.session.ssh.readyTimeout,
keepaliveInterval: socket.request.session.ssh.keepaliveInterval,
keepaliveCountMax: socket.request.session.ssh.keepaliveCountMax,
- debug: debug('ssh2')
- })
+ debug: debug('ssh2'),
+ });
} else {
- debugWebSSH2('Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ' + JSON.stringify(socket.handshake))
- socket.emit('ssherror', 'WEBSOCKET ERROR - Refresh the browser and try again')
- socket.request.session.destroy()
- socket.disconnect(true)
+ debugWebSSH2(`Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ${JSON.stringify(socket.handshake)}`);
+ socket.emit('ssherror', 'WEBSOCKET ERROR - Refresh the browser and try again');
+ socket.request.session.destroy();
+ socket.disconnect(true);
}
/**
@@ -161,33 +197,4 @@ module.exports = function socket (socket) {
* @param {object} err error object or error message
*/
// eslint-disable-next-line complexity
- function SSHerror (myFunc, err) {
- var theError
- if (socket.request.session) {
- // we just want the first error of the session to pass to the client
- socket.request.session.error = (socket.request.session.error) || ((err) ? err.message : undefined)
- theError = (socket.request.session.error) ? ': ' + socket.request.session.error : ''
- // log unsuccessful login attempt
- if (err && (err.level === 'client-authentication')) {
- console.log('WebSSH2 ' + 'error: Authentication failure'.red.bold +
- ' user=' + socket.request.session.username.yellow.bold.underline +
- ' from=' + socket.handshake.address.yellow.bold.underline)
- socket.emit('allowreauth', socket.request.session.ssh.allowreauth)
- socket.emit('reauth')
- } else {
- console.log('WebSSH2 Logout: user=' + socket.request.session.username + ' from=' + socket.handshake.address + ' host=' + socket.request.session.ssh.host + ' port=' + socket.request.session.ssh.port + ' sessionID=' + socket.request.sessionID + '/' + socket.id + ' allowreplay=' + socket.request.session.ssh.allowreplay + ' term=' + socket.request.session.ssh.term)
- if (err) {
- theError = (err) ? ': ' + err.message : ''
- console.log('WebSSH2 error' + theError)
- }
- }
- socket.emit('ssherror', 'SSH ' + myFunc + theError)
- socket.request.session.destroy()
- socket.disconnect(true)
- } else {
- theError = (err) ? ': ' + err.message : ''
- socket.disconnect(true)
- }
- debugWebSSH2('SSHerror ' + myFunc + theError)
- }
-}
+};