mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 16:23:28 +02:00
VNC authentication works, although there is no UI for adding passwords
yet. Direct database manipulation is required for now.
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
var util = require('util')
|
||||
var os = require('os')
|
||||
var crypto = require('crypto')
|
||||
|
||||
var EventEmitter = require('eventemitter3').EventEmitter
|
||||
var debug = require('debug')('vnc:connection')
|
||||
var Promise = require('bluebird')
|
||||
|
||||
var PixelFormat = require('./pixelformat')
|
||||
var vncauth = require('../../../../../util/vncauth')
|
||||
|
||||
function VncConnection(conn, options) {
|
||||
this.options = options
|
||||
@@ -21,7 +24,15 @@ function VncConnection(conn, options) {
|
||||
this._changeState(VncConnection.STATE_NEED_CLIENT_VERSION)
|
||||
|
||||
this._serverVersion = VncConnection.V3_008
|
||||
this._serverSupportedSecurity = [VncConnection.SECURITY_NONE]
|
||||
this._serverSupportedSecurity = this.options.security
|
||||
this._serverSupportedSecurityByType =
|
||||
this.options.security.reduce(
|
||||
function(map, method) {
|
||||
map[method.type] = method
|
||||
return map
|
||||
}
|
||||
, Object.create(null)
|
||||
)
|
||||
this._serverWidth = this.options.width
|
||||
this._serverHeight = this.options.height
|
||||
this._serverPixelFormat = new PixelFormat({
|
||||
@@ -45,12 +56,16 @@ function VncConnection(conn, options) {
|
||||
this._clientEncodings = []
|
||||
this._clientCutTextLength = 0
|
||||
|
||||
this._authChallenge = this.options.challenge || crypto.randomBytes(16)
|
||||
|
||||
this.conn = conn
|
||||
.on('error', this._bound._errorListener)
|
||||
.on('readable', this._bound._readableListener)
|
||||
.on('end', this._bound._endListener)
|
||||
.on('close', this._bound._closeListener)
|
||||
|
||||
this._blockingOps = []
|
||||
|
||||
this._writeServerVersion()
|
||||
this._read()
|
||||
}
|
||||
@@ -80,6 +95,7 @@ var StateReverse = Object.create(null), State = {
|
||||
STATE_NEED_CLIENT_VERSION: 10
|
||||
, STATE_NEED_CLIENT_SECURITY: 20
|
||||
, STATE_NEED_CLIENT_INIT: 30
|
||||
, STATE_NEED_CLIENT_VNC_AUTH: 31
|
||||
, STATE_NEED_CLIENT_MESSAGE: 40
|
||||
, STATE_NEED_CLIENT_MESSAGE_SETPIXELFORMAT: 50
|
||||
, STATE_NEED_CLIENT_MESSAGE_SETENCODINGS: 60
|
||||
@@ -171,18 +187,12 @@ VncConnection.prototype._writeSupportedSecurity = function() {
|
||||
|
||||
chunk[0] = this._serverSupportedSecurity.length
|
||||
this._serverSupportedSecurity.forEach(function(security, i) {
|
||||
chunk[1 + i] = security
|
||||
chunk[1 + i] = security.type
|
||||
})
|
||||
|
||||
this._write(chunk)
|
||||
}
|
||||
|
||||
VncConnection.prototype._writeSelectedSecurity = function() {
|
||||
var chunk = new Buffer(4)
|
||||
chunk.writeUInt32BE(VncConnection.SECURITY_NONE, 0)
|
||||
this._write(chunk)
|
||||
}
|
||||
|
||||
VncConnection.prototype._writeSecurityResult = function(result, reason) {
|
||||
var chunk
|
||||
switch (result) {
|
||||
@@ -224,11 +234,40 @@ VncConnection.prototype._writeServerInit = function() {
|
||||
this._write(chunk)
|
||||
}
|
||||
|
||||
VncConnection.prototype._writeVncAuthChallenge = function() {
|
||||
var vncSec = this._serverSupportedSecurityByType[VncConnection.SECURITY_VNC]
|
||||
debug('vnc auth challenge', vncSec.challenge)
|
||||
this._write(vncSec.challenge)
|
||||
}
|
||||
|
||||
VncConnection.prototype._readableListener = function() {
|
||||
this._read()
|
||||
}
|
||||
|
||||
VncConnection.prototype._read = function() {
|
||||
Promise.all(this._blockingOps).bind(this)
|
||||
.then(this._unguardedRead)
|
||||
}
|
||||
|
||||
VncConnection.prototype._auth = function(type, data) {
|
||||
var security = this._serverSupportedSecurityByType[type]
|
||||
this._blockingOps.push(
|
||||
security.auth(data).bind(this)
|
||||
.then(function() {
|
||||
this._changeState(VncConnection.STATE_NEED_CLIENT_INIT)
|
||||
this._writeSecurityResult(VncConnection.SECURITYRESULT_OK)
|
||||
this.emit('authenticated')
|
||||
this._read()
|
||||
})
|
||||
.catch(function() {
|
||||
this._writeSecurityResult(
|
||||
VncConnection.SECURITYRESULT_FAIL, 'Authentication failure')
|
||||
this.end()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
VncConnection.prototype._unguardedRead = function() {
|
||||
var chunk, lo, hi
|
||||
while (this._append(this.conn.read())) {
|
||||
do {
|
||||
@@ -250,14 +289,35 @@ VncConnection.prototype._read = function() {
|
||||
if ((chunk = this._consume(1))) {
|
||||
if ((this._clientSecurity = this._parseSecurity(chunk)) === null) {
|
||||
this._writeSecurityResult(
|
||||
VncConnection.SECURITYRESULT_FAIL, 'Unsupported security type')
|
||||
VncConnection.SECURITYRESULT_FAIL, 'Unimplemented security type')
|
||||
this.end()
|
||||
return
|
||||
}
|
||||
debug('client security', this._clientSecurity)
|
||||
this._writeSecurityResult(VncConnection.SECURITYRESULT_OK)
|
||||
this.emit('authenticated')
|
||||
this._changeState(VncConnection.STATE_NEED_CLIENT_INIT)
|
||||
if (!(this._clientSecurity in this._serverSupportedSecurityByType)) {
|
||||
this._writeSecurityResult(
|
||||
VncConnection.SECURITYRESULT_FAIL, 'Unsupported security type')
|
||||
this.end()
|
||||
return
|
||||
}
|
||||
switch (this._clientSecurity) {
|
||||
case VncConnection.SECURITY_NONE:
|
||||
this._auth(VncConnection.SECURITY_NONE)
|
||||
return
|
||||
case VncConnection.SECURITY_VNC:
|
||||
this._writeVncAuthChallenge()
|
||||
this._changeState(VncConnection.STATE_NEED_CLIENT_VNC_AUTH)
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
case VncConnection.STATE_NEED_CLIENT_VNC_AUTH:
|
||||
if ((chunk = this._consume(16))) {
|
||||
this._auth(VncConnection.SECURITY_VNC, {
|
||||
response: chunk
|
||||
, fingerprint: vncauth.format(chunk)
|
||||
})
|
||||
return
|
||||
}
|
||||
break
|
||||
case VncConnection.STATE_NEED_CLIENT_INIT:
|
||||
@@ -284,14 +344,17 @@ VncConnection.prototype._read = function() {
|
||||
VncConnection.STATE_NEED_CLIENT_MESSAGE_FBUPDATEREQUEST)
|
||||
break
|
||||
case VncConnection.CLIENT_MESSAGE_KEYEVENT:
|
||||
this.emit('userActivity')
|
||||
this._changeState(
|
||||
VncConnection.STATE_NEED_CLIENT_MESSAGE_KEYEVENT)
|
||||
break
|
||||
case VncConnection.CLIENT_MESSAGE_POINTEREVENT:
|
||||
this.emit('userActivity')
|
||||
this._changeState(
|
||||
VncConnection.STATE_NEED_CLIENT_MESSAGE_POINTEREVENT)
|
||||
break
|
||||
case VncConnection.CLIENT_MESSAGE_CLIENTCUTTEXT:
|
||||
this.emit('userActivity')
|
||||
this._changeState(
|
||||
VncConnection.STATE_NEED_CLIENT_MESSAGE_CLIENTCUTTEXT)
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user