refactor: socket.js

This commit is contained in:
Bill Church 2022-05-13 10:13:14 -04:00
parent 3438c93a14
commit 486e5dae0c

View file

@ -15,25 +15,15 @@ const dnsPromises = require('dns').promises;
let termCols; let termCols;
let termRows; let termRows;
// public /**
module.exports = function appSocket(socket) {
async function setupConnection() {
// 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;
}
/**
* Error handling for various events. Outputs error to client, logs to * Error handling for various events. Outputs error to client, logs to
* server, destroys session and disconnects socket. * server, destroys session and disconnects socket.
* @param {object} socket Socket information
* @param {string} myFunc Function calling this function * @param {string} myFunc Function calling this function
* @param {object} err error object or error message * @param {object} err error object or error message
*/ */
// eslint-disable-next-line complexity // eslint-disable-next-line complexity
function SSHerror(myFunc, err) { function SSHerror(socket, myFunc, err) {
let theError; let theError;
if (socket.request.session) { if (socket.request.session) {
// we just want the first error of the session to pass to the client // we just want the first error of the session to pass to the client
@ -66,12 +56,9 @@ module.exports = function appSocket(socket) {
socket.disconnect(true); socket.disconnect(true);
} }
debugWebSSH2(`SSHerror ${myFunc}${theError}`); debugWebSSH2(`SSHerror ${myFunc}${theError}`);
} }
// If configured, check that requsted host is in a permitted subnet
if ( async function checkSubnet(socket) {
(((socket.request.session || {}).ssh || {}).allowedSubnets || {}).length &&
socket.request.session.ssh.allowedSubnets.length > 0
) {
let ipaddress = socket.request.session.ssh.host; let ipaddress = socket.request.session.ssh.host;
if (!validator.isIP(`${ipaddress}`)) { if (!validator.isIP(`${ipaddress}`)) {
try { try {
@ -98,8 +85,23 @@ module.exports = function appSocket(socket) {
); );
socket.emit('ssherror', '401 UNAUTHORIZED'); socket.emit('ssherror', '401 UNAUTHORIZED');
socket.disconnect(true); socket.disconnect(true);
}
}
// public
module.exports = function appSocket(socket) {
async function setupConnection() {
// 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; return;
} }
// If configured, check that requsted host is in a permitted subnet
if (socket.request.session?.ssh?.allowedSubnets?.length > 0) {
checkSubnet(socket);
} }
const conn = new SSH(); const conn = new SSH();
@ -139,7 +141,7 @@ module.exports = function appSocket(socket) {
}, },
(err, stream) => { (err, stream) => {
if (err) { if (err) {
SSHerror(`EXEC ERROR${err}`); SSHerror(socket, `EXEC ERROR`, err);
conn.end(); conn.end();
return; return;
} }
@ -161,12 +163,12 @@ module.exports = function appSocket(socket) {
socket.on('disconnect', (reason) => { socket.on('disconnect', (reason) => {
debugWebSSH2(`SOCKET DISCONNECT: ${reason}`); debugWebSSH2(`SOCKET DISCONNECT: ${reason}`);
const errMsg = { message: reason }; const errMsg = { message: reason };
SSHerror('CLIENT SOCKET DISCONNECT', errMsg); SSHerror(socket, 'CLIENT SOCKET DISCONNECT', errMsg);
conn.end(); conn.end();
// socket.request.session.destroy() // socket.request.session.destroy()
}); });
socket.on('error', (errMsg) => { socket.on('error', (errMsg) => {
SSHerror('SOCKET ERROR', errMsg); SSHerror(socket, 'SOCKET ERROR', errMsg);
conn.end(); conn.end();
}); });
@ -174,15 +176,7 @@ module.exports = function appSocket(socket) {
socket.emit('data', data.toString('utf-8')); socket.emit('data', data.toString('utf-8'));
}); });
stream.on('close', (code, signal) => { stream.on('close', (code, signal) => {
const errMsg = { SSHerror(socket, 'STREAM CLOSE', { message: code, signal });
message:
code || signal
? (code ? `CODE: ${code}` : '') +
(code && signal ? ', ' : '') +
(signal ? `SIGNAL: ${signal}` : '')
: undefined,
};
SSHerror('STREAM CLOSE', errMsg);
conn.end(); conn.end();
}); });
stream.stderr.on('data', (data) => { stream.stderr.on('data', (data) => {
@ -193,15 +187,15 @@ module.exports = function appSocket(socket) {
}); });
conn.on('end', (err) => { conn.on('end', (err) => {
SSHerror('CONN END BY HOST', err); SSHerror(socket, 'CONN END BY HOST', err);
}); });
conn.on('close', (err) => { conn.on('close', (err) => {
SSHerror('CONN CLOSE', err); SSHerror(socket, 'CONN CLOSE', err);
}); });
conn.on('error', (err) => { conn.on('error', (err) => {
SSHerror('CONN ERROR', err); SSHerror(socket, 'CONN ERROR', err);
}); });
conn.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => { conn.on('keyboard-interactive', (_name, _instructions, _instructionsLang, _prompts, finish) => {
debugWebSSH2("conn.on('keyboard-interactive')"); debugWebSSH2("conn.on('keyboard-interactive')");
finish([socket.request.session.userpassword]); finish([socket.request.session.userpassword]);
}); });