From 545d503e91568c1eca8a31793fa2258fd3f8f118 Mon Sep 17 00:00:00 2001 From: Bill Church Date: Mon, 17 May 2021 06:43:28 -0400 Subject: [PATCH] chore: lint ./app/server/socket.js #242 --- app/server/socket.js | 265 ++++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 129 deletions(-) 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) - } -} +};