From 982780ed1d31d4b27bba3d1a9a2bfd88fb84f689 Mon Sep 17 00:00:00 2001 From: Bill Church Date: Mon, 17 May 2021 07:04:44 -0400 Subject: [PATCH] chore: linting for Prettier #242 --- app/server/app.js | 136 +++++++++++++--------- app/server/expressOptions.js | 8 +- app/server/socket.js | 213 +++++++++++++++++++++-------------- app/server/util.js | 12 +- 4 files changed, 219 insertions(+), 150 deletions(-) diff --git a/app/server/app.js b/app/server/app.js index 0b0de386..20efc4e1 100644 --- a/app/server/app.js +++ b/app/server/app.js @@ -71,16 +71,8 @@ let config = { 'aes256-gcm@openssh.com', 'aes256-cbc', ], - hmac: [ - 'hmac-sha2-256', - 'hmac-sha2-512', - 'hmac-sha1', - ], - compress: [ - 'none', - 'zlib@openssh.com', - 'zlib', - ], + hmac: ['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'], + compress: ['none', 'zlib@openssh.com', 'zlib'], }, serverlog: { client: false, @@ -99,11 +91,15 @@ try { console.log(`webssh2 service reading config from: ${configPath}`); config = require('read-config-ng')(configPath) // eslint-disable-line } else { - console.error(`\n\nERROR: Missing config.json for webssh. Current config: ${JSON.stringify(config)}`); + console.error( + `\n\nERROR: Missing config.json for webssh. Current config: ${JSON.stringify(config)}` + ); console.error('\n See config.json.sample for details\n\n'); } } catch (err) { - console.error(`\n\nERROR: Missing config.json for webssh. Current config: ${JSON.stringify(config)}`); + console.error( + `\n\nERROR: Missing config.json for webssh. Current config: ${JSON.stringify(config)}` + ); console.error('\n See config.json.sample for details\n\n'); console.error(`ERROR:\n\n ${err}`); } @@ -120,7 +116,11 @@ const app = express(); const server = require('http').Server(app); const validator = require('validator'); -const io = require('socket.io')(server, { serveClient: false, path: '/ssh/socket.io', origins: config.http.origins }); +const io = require('socket.io')(server, { + serveClient: false, + path: '/ssh/socket.io', + origins: config.http.origins, +}); const favicon = require('serve-favicon'); const appSocket = require('./socket'); const expressOptions = require('./expressOptions'); @@ -166,7 +166,11 @@ app.use(favicon(path.join(publicPath, 'favicon.ico'))); app.get('/ssh/reauth', (req, res) => { const r = req.headers.referer || '/'; - res.status(401).send(``); + res + .status(401) + .send( + `` + ); }); // eslint-disable-next-line complexity @@ -174,12 +178,14 @@ app.get('/ssh/host/:host?', (req, res) => { res.sendFile(path.join(path.join(publicPath, 'client.htm'))); // capture, assign, and validate variables req.session.ssh = { - host: config.ssh.host || (validator.isIP(`${req.params.host}`) && req.params.host) - || (validator.isFQDN(req.params.host) && req.params.host) - || (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.params.host) - && req.params.host), - port: (validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }) - && req.query.port) || config.ssh.port, + host: + config.ssh.host || + (validator.isIP(`${req.params.host}`) && req.params.host) || + (validator.isFQDN(req.params.host) && req.params.host) || + (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.params.host) && req.params.host), + port: + (validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }) && req.query.port) || + config.ssh.port, localAddress: config.ssh.localAddress, localPort: config.ssh.localPort, header: { @@ -190,23 +196,44 @@ app.get('/ssh/host/:host?', (req, res) => { keepaliveInterval: config.ssh.keepaliveInterval, keepaliveCountMax: config.ssh.keepaliveCountMax, allowedSubnets: config.ssh.allowedSubnets, - term: (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) - && req.query.sshterm) || config.ssh.term, + term: + (/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) && req.query.sshterm) || + config.ssh.term, terminal: { - cursorBlink: (validator.isBoolean(`${req.query.cursorBlink}`) ? myutil.parseBool(req.query.cursorBlink) : config.terminal.cursorBlink), - scrollback: (validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 }) && req.query.scrollback) ? req.query.scrollback : config.terminal.scrollback, - tabStopWidth: (validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 }) && req.query.tabStopWidth) ? req.query.tabStopWidth : config.terminal.tabStopWidth, - bellStyle: ((req.query.bellStyle) && (['sound', 'none'].indexOf(req.query.bellStyle) > -1)) ? req.query.bellStyle : config.terminal.bellStyle, + cursorBlink: validator.isBoolean(`${req.query.cursorBlink}`) + ? myutil.parseBool(req.query.cursorBlink) + : config.terminal.cursorBlink, + scrollback: + validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 }) && req.query.scrollback + ? req.query.scrollback + : config.terminal.scrollback, + tabStopWidth: + validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 }) && req.query.tabStopWidth + ? req.query.tabStopWidth + : config.terminal.tabStopWidth, + bellStyle: + req.query.bellStyle && ['sound', 'none'].indexOf(req.query.bellStyle) > -1 + ? req.query.bellStyle + : config.terminal.bellStyle, }, - allowreplay: config.options.challengeButton || (validator.isBoolean(`${req.headers.allowreplay}`) ? myutil.parseBool(req.headers.allowreplay) : false), + allowreplay: + config.options.challengeButton || + (validator.isBoolean(`${req.headers.allowreplay}`) + ? myutil.parseBool(req.headers.allowreplay) + : false), allowreauth: config.options.allowreauth || false, - mrhsession: ((validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession) ? req.headers.mrhsession : 'none'), + mrhsession: + validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession + ? req.headers.mrhsession + : 'none', serverlog: { client: config.serverlog.client || false, server: config.serverlog.server || false, }, - readyTimeout: (validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 }) - && req.query.readyTimeout) || config.ssh.readyTimeout, + readyTimeout: + (validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 }) && + req.query.readyTimeout) || + config.ssh.readyTimeout, }; if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name); if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background); @@ -228,9 +255,7 @@ io.on('connection', appSocket); // socket.io // expose express session with socket.request.session io.use((socket, next) => { - (socket.request.res) - ? session(socket.request, socket.request.res, next) - : next(next); // eslint disable-line + socket.request.res ? session(socket.request, socket.request.res, next) : next(next); // eslint disable-line }); io.on('connection', (socket) => { @@ -238,32 +263,33 @@ io.on('connection', (socket) => { socket.on('disconnect', () => { connectionCount -= 1; - if ((connectionCount <= 0) && shutdownMode) { + if (connectionCount <= 0 && shutdownMode) { stopApp('All clients disconnected'); } }); }); const signals = ['SIGTERM', 'SIGINT']; -signals.forEach((signal) => process.on(signal, () => { - if (shutdownMode) stopApp('Safe shutdown aborted, force quitting'); - else if (connectionCount > 0) { - let remainingSeconds = config.safeShutdownDuration; - shutdownMode = true; - const message = (connectionCount === 1) - ? ' client is still connected' - : ' clients are still connected'; - console.error(connectionCount + message); - console.error(`Starting a ${remainingSeconds} seconds countdown`); - console.error('Press Ctrl+C again to force quit'); +signals.forEach((signal) => + process.on(signal, () => { + if (shutdownMode) stopApp('Safe shutdown aborted, force quitting'); + else if (connectionCount > 0) { + let remainingSeconds = config.safeShutdownDuration; + shutdownMode = true; + const message = + connectionCount === 1 ? ' client is still connected' : ' clients are still connected'; + console.error(connectionCount + message); + console.error(`Starting a ${remainingSeconds} seconds countdown`); + console.error('Press Ctrl+C again to force quit'); - shutdownInterval = setInterval(() => { - remainingSeconds -= 1; - if ((remainingSeconds) <= 0) { - stopApp('Countdown is over'); - } else { - io.sockets.emit('shutdownCountdownUpdate', remainingSeconds); - } - }, 1000); - } else stopApp(); -})); + shutdownInterval = setInterval(() => { + remainingSeconds -= 1; + if (remainingSeconds <= 0) { + stopApp('Countdown is over'); + } else { + io.sockets.emit('shutdownCountdownUpdate', remainingSeconds); + } + }, 1000); + } else stopApp(); + }) +); diff --git a/app/server/expressOptions.js b/app/server/expressOptions.js index 86d48419..953fbf99 100644 --- a/app/server/expressOptions.js +++ b/app/server/expressOptions.js @@ -5,7 +5,7 @@ module.exports = { index: false, maxAge: '1s', redirect: false, - setHeaders: function (res, path, stat) { - res.set('x-timestamp', Date.now()) - } -} + setHeaders(res) { + res.set('x-timestamp', Date.now()); + }, +}; diff --git a/app/server/socket.js b/app/server/socket.js index 6ccd64f1..64d7d2d2 100644 --- a/app/server/socket.js +++ b/app/server/socket.js @@ -13,8 +13,9 @@ const CIDRMatcher = require('cidr-matcher'); // var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8')) let termCols; let termRows; -const menuData = ' Start Log' - + ' Download Log'; +const menuData = + ' Start Log' + + ' Download Log'; // public module.exports = function appSocket(socket) { @@ -30,21 +31,24 @@ module.exports = function appSocket(socket) { 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}` : ''; + 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}`); + 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}`); + 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}` : ''; + theError = err ? `: ${err.message}` : ''; console.error(`WebSSH2 error${theError}`); } } @@ -52,19 +56,23 @@ module.exports = function appSocket(socket) { socket.request.session.destroy(); socket.disconnect(true); } else { - theError = (err) ? `: ${err.message}` : ''; + 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)) { + 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.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}`); + 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; @@ -82,33 +90,42 @@ module.exports = function appSocket(socket) { }); 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}`); + 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}`); + 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, - }, (err, stream) => { - if (err) { - 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', (data) => { - stream.write(data); + conn.shell( + { + term: socket.request.session.ssh.term, + cols: termCols, + rows: termRows, + }, + (err, stream) => { + if (err) { + SSHerror(`EXEC ERROR${err}`); + conn.end(); + return; + } // poc to log commands from client - /* if (socket.request.session.ssh.serverlog.client) { + // 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 (data === '\r') { console.log(`serverlog.client: ${socket.request.session.id}/${socket.id} host: ${socket.request.session.ssh.host} command: ${dataBuffer}`); @@ -117,56 +134,76 @@ module.exports = function appSocket(socket) { dataBuffer = (dataBuffer) ? dataBuffer + data : data; } } */ - }); - socket.on('control', (controlData) => { - switch (controlData) { - case 'replayCredentials': - if (socket.request.session.ssh.allowreplay) { - stream.write(`${socket.request.session.userpassword}\n`); - } - /* falls through */ - default: - debugWebSSH2(`controlData: ${controlData}`); - } - }); - 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', (errMsg) => { - SSHerror('SOCKET ERROR', errMsg); - conn.end(); - }); + }); + socket.on('control', (controlData) => { + switch (controlData) { + case 'replayCredentials': + if (socket.request.session.ssh.allowreplay) { + stream.write(`${socket.request.session.userpassword}\n`); + } + /* falls through */ + default: + debugWebSSH2(`controlData: ${controlData}`); + } + }); + 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', (errMsg) => { + SSHerror('SOCKET ERROR', errMsg); + conn.end(); + }); - 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}`); - }); - }); + 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', (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('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\')'); + 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) { + 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, @@ -184,17 +221,21 @@ module.exports = function appSocket(socket) { 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)}`); + 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); } /** - * Error handling for various events. Outputs error to client, logs to - * server, destroys session and disconnects socket. - * @param {string} myFunc Function calling this function - * @param {object} err error object or error message - */ + * Error handling for various events. Outputs error to client, logs to + * server, destroys session and disconnects socket. + * @param {string} myFunc Function calling this function + * @param {object} err error object or error message + */ // eslint-disable-next-line complexity }; diff --git a/app/server/util.js b/app/server/util.js index f6fbc9cf..ff5ebf4e 100644 --- a/app/server/util.js +++ b/app/server/util.js @@ -19,15 +19,17 @@ exports.basicAuth = function basicAuth(req, res, next) { if (myAuth && myAuth.pass !== '') { req.session.username = myAuth.name; req.session.userpassword = myAuth.pass; - debug(`myAuth.name: ${myAuth.name.yellow.bold.underline - } and password ${(myAuth.pass) ? 'exists'.yellow.bold.underline - : 'is blank'.underline.red.bold}`); + debug( + `myAuth.name: ${myAuth.name.yellow.bold.underline} and password ${ + myAuth.pass ? 'exists'.yellow.bold.underline : 'is blank'.underline.red.bold + }` + ); } else { req.session.username = defaultCredentials.username; req.session.userpassword = defaultCredentials.password; req.session.privatekey = defaultCredentials.privatekey; } - if ((!req.session.userpassword) && (!req.session.privatekey)) { + if (!req.session.userpassword && !req.session.privatekey) { res.statusCode = 401; debug('basicAuth credential request (401)'); res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH"'); @@ -39,5 +41,5 @@ exports.basicAuth = function basicAuth(req, res, next) { // takes a string, makes it boolean (true if the string is true, false otherwise) exports.parseBool = function parseBool(str) { - return (str.toLowerCase() === 'true'); + return str.toLowerCase() === 'true'; };