reauth feature

fixes #75 and potentially #51 thanks to both @vbeskrovny and @vvalchev
This commit is contained in:
Bill Church 2018-07-30 09:54:36 -04:00
parent a518f0748f
commit 9bbc116120
8 changed files with 36 additions and 23 deletions

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.xterm{font-family:courier-new,courier,monospace;font-feature-settings:"liga" 0;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:10}.xterm .xterm-helper-textarea{position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-10;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm:not(.enable-mouse-events){cursor:text}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:100;color:transparent}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-cursor-pointer{cursor:pointer}body,html{font-family:helvetica,sans-serif;font-size:1em;color:#111;background-color:#000;color:#f0f0f0;height:100%;margin:0}#header{color:#f0f0f0;background-color:green;width:100%;border-color:#fff;border-style:none none solid;border-width:1px;text-align:center;flex:0 1 auto;z-index:99;height:19px;display:none}.box{display:block;height:100%}#terminal-container{display:block;width:calc(1 - 1 px);margin:0 auto;padding:2px;height:calc(100% - 19px)}#terminal-container .terminal{background-color:#000;color:#fafafa;padding:2px;height:calc(100% - 19px)}#terminal-container .terminal:focus .terminal-cursor{background-color:#fafafa}#bottomdiv{position:fixed;left:0;bottom:0;width:100%;background-color:#323232;border-color:#fff;border-style:solid none none;border-width:1px;z-index:99;height:19px}#footer{padding-left:5px;padding-right:5px;border-style:none none none solid}#footer,#status{display:inline-block;color:#f0f0f0;background-color:#323232;border-color:#fff;border-width:1px;text-align:left}#status{padding-right:10px;border-style:none solid}#menu,#status{padding-left:10px;z-index:100}#menu{display:inline-block;font-size:16px;color:#fff}#menu:hover .dropup-content{display:block}#credentialsBtn,#logBtn{color:#000}.dropup{position:relative;display:inline-block;cursor:pointer}.dropup-content{display:none;position:absolute;background-color:#f1f1f1;font-size:16px;min-width:160px;bottom:18px;z-index:101}.dropup-content a{color:#777;padding:12px 16px;text-decoration:none;display:block}.dropup-content a:hover{background-color:#ccc}.dropup:click .dropup-content,.dropup:hover .dropup-content{display:block}.dropup:hover .dropbtn{background-color:#3e8e41} .xterm{font-family:courier-new,courier,monospace;font-feature-settings:"liga" 0;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:10}.xterm .xterm-helper-textarea{position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-10;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm:not(.enable-mouse-events){cursor:text}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:100;color:transparent}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-cursor-pointer{cursor:pointer}body,html{font-family:helvetica,sans-serif;font-size:1em;color:#111;background-color:#000;color:#f0f0f0;height:100%;margin:0}#header{color:#f0f0f0;background-color:green;width:100%;border-color:#fff;border-style:none none solid;border-width:1px;text-align:center;flex:0 1 auto;z-index:99;height:19px;display:none}.box{display:block;height:100%}#terminal-container{display:block;width:calc(1 - 1 px);margin:0 auto;padding:2px;height:calc(100% - 19px)}#terminal-container .terminal{background-color:#000;color:#fafafa;padding:2px;height:calc(100% - 19px)}#terminal-container .terminal:focus .terminal-cursor{background-color:#fafafa}#bottomdiv{position:fixed;left:0;bottom:0;width:100%;background-color:#323232;border-color:#fff;border-style:solid none none;border-width:1px;z-index:99;height:19px}#footer{padding-left:5px;padding-right:5px;border-style:none none none solid}#footer,#status{display:inline-block;color:#f0f0f0;background-color:#323232;border-color:#fff;border-width:1px;text-align:left}#status{padding-right:10px;border-style:none solid}#menu,#status{padding-left:10px;z-index:100}#menu{display:inline-block;font-size:16px;color:#fff}#menu:hover .dropup-content{display:block}#credentialsBtn,#logBtn,#reauthBtn{color:#000}.dropup{position:relative;display:inline-block;cursor:pointer}.dropup-content{display:none;position:absolute;background-color:#f1f1f1;font-size:16px;min-width:160px;bottom:18px;z-index:101}.dropup-content a{color:#777;padding:12px 16px;text-decoration:none;display:block}.dropup-content a:hover{background-color:#ccc}.dropup:click .dropup-content,.dropup:hover .dropup-content{display:block}.dropup:hover .dropbtn{background-color:#3e8e41}

View file

@ -85,12 +85,10 @@ html, body {
#menu:hover .dropup-content { #menu:hover .dropup-content {
display: block; display: block;
} }
#logBtn { #logBtn, #credentialsBtn, #reauthBtn {
color: #000;
}
#credentialsBtn {
color: #000; color: #000;
} }
.dropup { .dropup {
position: relative; position: relative;
display: inline-block; display: inline-block;

View file

@ -19,10 +19,11 @@ require('../css/style.css')
Terminal.applyAddon(fit) Terminal.applyAddon(fit)
/* global Blob, logBtn, credentialsBtn, downloadLogBtn */ /* global Blob, logBtn, credentialsBtn, reauthBtn, downloadLogBtn */
var sessionLogEnable = false var sessionLogEnable = false
var loggedData = false var loggedData = false
var allowreplay = false var allowreplay = false
var allowreauth = false
var sessionLog, sessionFooter, logDate, currentDate, myFile, errorExists var sessionLog, sessionFooter, logDate, currentDate, myFile, errorExists
var socket, termid // eslint-disable-line var socket, termid // eslint-disable-line
var term = new Terminal() var term = new Terminal()
@ -128,6 +129,17 @@ socket.on('allowreplay', function (data) {
} }
}) })
socket.on('allowreauth', function (data) {
if (data === true) {
console.log('allowreauth: ' + data)
allowreauth = true
drawMenu(dropupContent.innerHTML + '<a id="reauthBtn"><i class="fas fa-key fa-fw"></i> Switch User</a>')
} else {
allowreauth = false
console.log('allowreauth: ' + data)
}
})
socket.on('disconnect', function (err) { socket.on('disconnect', function (err) {
if (!errorExists) { if (!errorExists) {
status.style.backgroundColor = 'red' status.style.backgroundColor = 'red'
@ -153,10 +165,18 @@ term.on('title', function (title) {
function drawMenu (data) { function drawMenu (data) {
dropupContent.innerHTML = data dropupContent.innerHTML = data
logBtn.addEventListener('click', toggleLog) logBtn.addEventListener('click', toggleLog)
allowreauth && reauthBtn.addEventListener('click', reauthSession)
allowreplay && credentialsBtn.addEventListener('click', replayCredentials) allowreplay && credentialsBtn.addEventListener('click', replayCredentials)
loggedData && downloadLogBtn.addEventListener('click', downloadLog) loggedData && downloadLogBtn.addEventListener('click', downloadLog)
} }
// reauthenticate
function reauthSession () { // eslint-disable-line
console.log('re-authenticating')
window.location.href = '/reauth'
return false
}
// replay password to server, requires // replay password to server, requires
function replayCredentials () { // eslint-disable-line function replayCredentials () { // eslint-disable-line
socket.emit('control', 'replayCredentials') socket.emit('control', 'replayCredentials')

View file

@ -30,7 +30,8 @@
"secret": "mysecret" "secret": "mysecret"
}, },
"options": { "options": {
"challengeButton": true "challengeButton": true,
"allowreauth": true
}, },
"algorithms": { "algorithms": {
"kex": [ "kex": [

View file

@ -45,7 +45,7 @@
"builddev": "webpack --progress --colors --config scripts/webpack.dev.js", "builddev": "webpack --progress --colors --config scripts/webpack.dev.js",
"test": "snyk test", "test": "snyk test",
"watch": "nodemon index.js", "watch": "nodemon index.js",
"standard": "standard --verbose | snazzy", "standard": "standard --verbose --fix | snazzy",
"cleanmac": "find . -name '.DS_Store' -type f -delete" "cleanmac": "find . -name '.DS_Store' -type f -delete"
}, },
"devDependencies": { "devDependencies": {
@ -78,7 +78,8 @@
"bigip/*", "bigip/*",
"screenshots/*", "screenshots/*",
"bin/*", "bin/*",
"build/*" "build/*",
"workspace/*"
] ]
} }
} }

View file

@ -36,16 +36,8 @@ app.disable('x-powered-by')
app.use(express.static(publicPath, expressOptions)) app.use(express.static(publicPath, expressOptions))
app.get('/reauth', function (req, res, next) { app.get('/reauth', function (req, res, next) {
var r = req.headers.referer || '/'; var r = req.headers.referer || '/'
res.status(401).send( res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=' + r + '"></head><body bgcolor="#000"></body></html>');
'<html>' +
' <head>' +
' <meta http-equiv="refresh" content="1; url=' + r + '" />' +
' </head>' +
' <body>' +
' <a href="' + r + '">Go Back</a>' +
' </body>' +
'</html>');
}) })
app.get('/ssh/host/:host?', function (req, res, next) { app.get('/ssh/host/:host?', function (req, res, next) {
@ -73,7 +65,8 @@ app.get('/ssh/host/:host?', function (req, res, next) {
tabStopWidth: (validator.isInt(req.query.tabStopWidth + '', {min: 1, max: 100}) && req.query.tabStopWidth) ? req.query.tabStopWidth : config.terminal.tabStopWidth, 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 bellStyle: ((req.query.bellStyle) && (['sound', 'none'].indexOf(req.query.bellStyle) > -1)) ? req.query.bellStyle : config.terminal.bellStyle
}, },
allowreplay: (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: { serverlog: {
client: config.serverlog.client || false, client: config.serverlog.client || false,

View file

@ -8,8 +8,7 @@ var SSH = require('ssh2').Client
// var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8')) // var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8'))
var termCols, termRows var termCols, termRows
var menuData = '<a id="logBtn"><i class="fas fa-clipboard fa-fw"></i> Start Log</a>' + var menuData = '<a id="logBtn"><i class="fas fa-clipboard fa-fw"></i> Start Log</a>' +
'<a id="downloadLogBtn"><i class="fas fa-download fa-fw"></i> Download Log</a>' + '<a id="downloadLogBtn"><i class="fas fa-download fa-fw"></i> Download Log</a>'
'<a style="color:black" href="/reauth"><i class="fas fa-key fa-fw"></i> Switch User</a>';
// public // public
module.exports = function socket (socket) { module.exports = function socket (socket) {
@ -42,6 +41,7 @@ module.exports = function socket (socket) {
socket.emit('status', 'SSH CONNECTION ESTABLISHED') socket.emit('status', 'SSH CONNECTION ESTABLISHED')
socket.emit('statusBackground', 'green') socket.emit('statusBackground', 'green')
socket.emit('allowreplay', socket.request.session.ssh.allowreplay) socket.emit('allowreplay', socket.request.session.ssh.allowreplay)
socket.emit('allowreauth', socket.request.session.ssh.allowreauth)
conn.shell({ conn.shell({
term: socket.request.session.ssh.term, term: socket.request.session.ssh.term,
cols: termCols, cols: termCols,