diff --git a/app.js b/app.js new file mode 100644 index 0000000..dbbb9fe --- /dev/null +++ b/app.js @@ -0,0 +1,159 @@ +var express = require('express'); +var http = require('http'); +var https = require('https'); +var path = require('path'); +var server = require('socket.io'); +var pty = require('node-pty'); +var fs = require('fs'); +var url = require('url'); + +var opts = require('optimist') + .options({ + sslkey: { + demand: false, + description: 'path to SSL key' + }, + sslcert: { + demand: false, + description: 'path to SSL certificate' + }, + sshhost: { + demand: false, + description: 'ssh server host' + }, + sshport: { + demand: false, + description: 'ssh server port' + }, + sshuser: { + demand: false, + description: 'ssh user' + }, + sshauth: { + demand: false, + description: 'defaults to "password", you can use "publickey,password" instead' + }, + port: { + demand: true, + alias: 'p', + description: 'wetty listen port' + }, + }).boolean('allow_discovery').argv; + +var runhttps = false; +var sshport = 22; +var sshhost = 'localhost'; +var sshauth = 'password,keyboard-interactive'; +var askusername = false; +var globalsshuser = ''; +var globalsshpass = ''; +var serveraliveinterval = 60; + +if (opts.sshport) { + sshport = opts.sshport; +} + +if (opts.sshhost) { + sshhost = opts.sshhost; +} + +if (opts.sshauth) { + sshauth = opts.sshauth +} + +if (opts.sshuser) { + globalsshuser = opts.sshuser; +} + +if (opts.sslkey && opts.sslcert) { + runhttps = true; + opts['ssl'] = {}; + opts.ssl['key'] = fs.readFileSync(path.resolve(opts.sslkey)); + opts.ssl['cert'] = fs.readFileSync(path.resolve(opts.sslcert)); +} + +process.on('uncaughtException', function(e) { + console.error('Error: ' + e); +}); + +var httpserv; + +var app = express(); +app.get('/wetty/ssh/:user', function(req, res) { + res.sendfile(__dirname + '/public/wetty/index.html'); +}); +app.get('/wetty/autologin', function(req, res) { + res.sendfile(__dirname + '/public/wetty/index.html'); +}); +app.use('/', express.static(path.join(__dirname, 'public'))); + +if (runhttps) { + httpserv = https.createServer(opts.ssl, app).listen(opts.port, function() { + console.log('https on port ' + opts.port); + }); +} else { + httpserv = http.createServer(app).listen(opts.port, function() { + console.log('http on port ' + opts.port); + }); +} + +var io = server(httpserv,{path: '/wetty/socket.io'}); +io.on('connection', function(socket){ + var sshuser = ''; + var sshpass = ''; + var request = socket.request; + console.log((new Date()) + ' Connection accepted.'); + if (match = request.headers.referer.match('/wetty/ssh/.+$')) { + sshuser = match[0].replace('/wetty/ssh/', ''); + } else if(match = request.headers.referer.match('/wetty/autologin.+$')){ + var referer = url.parse(request.headers.referer,true); + sshuser = referer.query.sshuser? referer.query.sshuser:globalsshuser; + sshpass = referer.query.sshpass? referer.query.sshpass:globalsshpass; + } else if (globalsshuser) { + sshuser = globalsshuser; + sshpass = globalsshpass; + } + + var term; + if (process.getuid() == 0) { + term = pty.spawn('/usr/bin/env', ['login'], { + name: 'xterm-256color', + cols: 80, + rows: 30 + }); + } else if(sshuser && sshpass) { + term = pty.spawn('/usr/bin/sshpass', ['-p', sshpass, 'ssh', sshuser + "@" + sshhost, '-p', sshport, '-o', 'PreferredAuthentications=' + sshauth, '-o', 'ServerAliveInterval=' + serveraliveinterval], { + name: 'xterm-256color', + cols: 80, + rows: 30 + }); + } else if(askusername){ + term = pty.spawn('/usr/bin/env', ['login'], { + name: 'xterm-256color', + cols: 80, + rows: 30 + }); + } else { + term = pty.spawn('ssh', [sshuser + "@" + sshhost, '-p', sshport, '-o', 'PreferredAuthentications=' + sshauth], { + name: 'xterm-256color', + cols: 80, + rows: 30 + }); + } + console.log((new Date()) + " PID=" + term.pid + " STARTED on behalf of user=" + sshuser) + term.on('data', function(data) { + socket.emit('output', data); + }); + term.on('exit', function(code) { + console.log((new Date()) + " PID=" + term.pid + " ENDED") + }); + socket.on('resize', function(data) { + term.resize(data.col, data.row); + }); + socket.on('input', function(data) { + term.write(data); + }); + socket.on('disconnect', function() { + term.end(); + }); +})