diff --git a/app/connectionHandler.js b/app/connectionHandler.js index d649418..6cd1283 100644 --- a/app/connectionHandler.js +++ b/app/connectionHandler.js @@ -7,56 +7,53 @@ var extend = require("util")._extend function handleConnection(req, res, urlParams) { urlParams = urlParams || {} - // The path to the client directory of the webssh2 module. - var clientPath = path.resolve( + const clientPath = path.resolve( __dirname, - "..", - "node_modules", - "webssh2_client", - "client", - "public" + '..', + 'node_modules', + 'webssh2_client', + 'client', + 'public' ) - // Combine URL parameters, query parameters, and form data - var connectionParams = extend({}, urlParams) + const connectionParams = extend({}, urlParams) extend(connectionParams, req.query) extend(connectionParams, req.body || {}) - // Inject configuration - var config = { + const sshCredentials = req.session.sshCredentials || {} + + const config = { socket: { - url: req.protocol + "://" + req.get("host"), - path: "/ssh/socket.io" + url: req.protocol + '://' + req.get('host'), + path: '/ssh/socket.io' }, ssh: { - host: urlParams.host || "", - port: urlParams.port || 22 + host: urlParams.host || sshCredentials.host || '', + port: urlParams.port || sshCredentials.port || 22, + username: sshCredentials.username || '', + password: sshCredentials.password || '' }, autoConnect: !!req.session.sshCredentials } - // Read the client.htm file fs.readFile( - path.join(clientPath, "client.htm"), - "utf8", + path.join(clientPath, 'client.htm'), + 'utf8', function (err, data) { if (err) { - return res.status(500).send("Error loading client file") + return res.status(500).send('Error loading client file') } - // Replace relative paths with the correct path var modifiedHtml = data.replace( /(src|href)="(?!http|\/\/)/g, '$1="/ssh/assets/' ) - // Inject the configuration into the HTML modifiedHtml = modifiedHtml.replace( - "window.webssh2Config = null;", - "window.webssh2Config = " + JSON.stringify(config) + ";" + 'window.webssh2Config = null;', + 'window.webssh2Config = ' + JSON.stringify(config) + ';' ) - // Send the modified HTML res.send(modifiedHtml) } ) diff --git a/app/routes.js b/app/routes.js index 7f615fc..5550835 100644 --- a/app/routes.js +++ b/app/routes.js @@ -1,34 +1,48 @@ // server // /app/routes.js -const createDebug = require("debug") -const debug = createDebug("webssh2:routes") -const express = require("express") +const createDebug = require('debug') +const debug = createDebug('webssh2:routes') +const express = require('express') const router = express.Router() -const handleConnection = require("./connectionHandler") -const basicAuth = require("basic-auth") +const handleConnection = require('./connectionHandler') +const basicAuth = require('basic-auth') function auth(req, res, next) { - debug("Authenticating user with HTTP Basic Auth") + debug('Authenticating user with HTTP Basic Auth') var credentials = basicAuth(req) if (!credentials) { - res.setHeader("WWW-Authenticate", 'Basic realm="WebSSH2"') - return res.status(401).send("Authentication required.") + res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH2"') + return res.status(401).send('Authentication required.') } // Store credentials in session - req.session.sshCredentials = credentials + req.session.sshCredentials = { + username: credentials.name, + password: credentials.pass + } next() } // Scenario 1: No auth required, uses websocket authentication instead -router.get("/", function (req, res) { - debug("Accessed /ssh route") +router.get('/', function (req, res) { + debug('Accessed / route') handleConnection(req, res) }) // Scenario 2: Auth required, uses HTTP Basic Auth -router.get("/host/:host", auth, function (req, res) { +router.get('/host/:host', auth, function (req, res) { debug(`Accessed /ssh/host/${req.params.host} route`) handleConnection(req, res, { host: req.params.host }) }) +// Clear credentials route +router.post('/clear-credentials', function (req, res) { + req.session.sshCredentials = null + res.status(200).send('Credentials cleared.') +}) + +router.post("/force-reconnect", function (req, res) { + req.session.sshCredentials = null; + res.status(401).send("Authentication required."); +}); + module.exports = router diff --git a/app/socket.js b/app/socket.js index 032af98..a9ae555 100644 --- a/app/socket.js +++ b/app/socket.js @@ -86,12 +86,27 @@ function handleConnection(socket, config) { * @param {Object} config - The configuration object */ function handleAuthentication(socket, creds, config) { - debug(`AUTHENTICATE: ${socket.id}, Host: ${creds.host}`) + // If reauth, creds from this function should take precedence + if (creds && isValidCredentials(creds)) { + // Store new credentials in session, overriding any existing ones + socket.handshake.session.sshCredentials = { + username: creds.username, + password: creds.password, + host: creds.host, + port: creds.port + } - if (isValidCredentials(creds)) { - debug(`CREDENTIALS VALID: ${socket.id}, Host: ${creds.host}`) + // Save the session after updating + socket.handshake.session.save((err) => { + if (err) { + console.error(`Failed to save session for ${socket.id}:`, err) + } + }) + + // Proceed with connection initialization using the new credentials initializeConnection(socket, creds, config) } else { + // Handle invalid credentials scenario debug(`CREDENTIALS INVALID: ${socket.id}, Host: ${creds.host}`) socket.emit("authentication", { success: false, @@ -331,8 +346,22 @@ function handleConnection(socket, config) { */ function handleReauth(socket) { debug(`Reauthentication requested for ${socket.id}`) - socket.emit("authentication", { action: "reauth" }) - handleConnectionClose(socket) + + // Clear existing session credentials + socket.handshake.session.sshCredentials = null + + // Save the session after modification + socket.handshake.session.save((err) => { + if (err) { + console.error(`Failed to save session for ${socket.id}:`, err) + } + + // Notify client to reauthenticate + socket.emit("authentication", { action: "reauth" }) + + // Close the current connection to enforce reauthentication + handleConnectionClose(socket) + }) } /**