diff --git a/core/rfb.js b/core/rfb.js index 3b52c29f4..876255ba2 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -1455,13 +1455,13 @@ export default class RFB extends EventTargetMixin { this._sock.send([ (user.length >> 24) & 0xFF, (user.length >> 16) & 0xFF, - (user.legnth >> 8) & 0xFF, + (user.length >> 8) & 0xFF, user.length & 0xFF ]); this._sock.send([ (pass.length >> 24) & 0xFF, (pass.length >> 16) & 0xFF, - (pass.legnth >> 8) & 0xFF, + (pass.length >> 8) & 0xFF, pass.length & 0xFF ]); this._sock.sendString(user); diff --git a/tests/test.rfb.js b/tests/test.rfb.js index d5a9adc81..09b6d1cc6 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1378,6 +1378,102 @@ describe('Remote Frame Buffer Protocol Client', function () { expect(client._fail).to.have.been.calledOnce; }); }); + + describe('VeNCrypt Authentication (type 19) Handler', function () { + beforeEach(function () { + client._rfbInitState = 'Security'; + client._rfbVersion = 3.8; + sendSecurity(19, client); + expect(client._sock).to.have.sent(new Uint8Array([19])); + }); + + it('should fail with non-0.2 versions', function () { + sinon.spy(client, "_fail"); + client._sock._websocket._receiveData(new Uint8Array([0, 1])); + expect(client._fail).to.have.been.calledOnce; + }); + + it('should fail if the Plain authentication is not present', function () { + // VeNCrypt version + client._sock._websocket._receiveData(new Uint8Array([0, 2])); + expect(client._sock).to.have.sent(new Uint8Array([0, 2])); + // Server ACK. + client._sock._websocket._receiveData(new Uint8Array([0])); + // Subtype list, only list subtype 1. + sinon.spy(client, "_fail"); + client._sock._websocket._receiveData(new Uint8Array([1, 0, 0, 0, 1])); + expect(client._fail).to.have.been.calledOnce; + }); + + it('should support Plain authentication', function () { + client._rfbCredentials = { username: 'username', password: 'password' }; + // VeNCrypt version + client._sock._websocket._receiveData(new Uint8Array([0, 2])); + expect(client._sock).to.have.sent(new Uint8Array([0, 2])); + // Server ACK. + client._sock._websocket._receiveData(new Uint8Array([0])); + // Subtype list. + client._sock._websocket._receiveData(new Uint8Array([1, 0, 0, 1, 0])); + + const expectedResponse = []; + push32(expectedResponse, 256); // Chosen subtype. + push32(expectedResponse, client._rfbCredentials.username.length); + push32(expectedResponse, client._rfbCredentials.password.length); + pushString(expectedResponse, client._rfbCredentials.username); + pushString(expectedResponse, client._rfbCredentials.password); + expect(client._sock).to.have.sent(new Uint8Array(expectedResponse)); + + client._initMsg = sinon.spy(); + client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 0])); + expect(client._initMsg).to.have.been.called; + }); + + it('should support Plain authentication with an empty password', function () { + client._rfbCredentials = { username: 'username', password: '' }; + // VeNCrypt version + client._sock._websocket._receiveData(new Uint8Array([0, 2])); + expect(client._sock).to.have.sent(new Uint8Array([0, 2])); + // Server ACK. + client._sock._websocket._receiveData(new Uint8Array([0])); + // Subtype list. + client._sock._websocket._receiveData(new Uint8Array([1, 0, 0, 1, 0])); + + const expectedResponse = []; + push32(expectedResponse, 256); // Chosen subtype. + push32(expectedResponse, client._rfbCredentials.username.length); + push32(expectedResponse, client._rfbCredentials.password.length); + pushString(expectedResponse, client._rfbCredentials.username); + pushString(expectedResponse, client._rfbCredentials.password); + expect(client._sock).to.have.sent(new Uint8Array(expectedResponse)); + + client._initMsg = sinon.spy(); + client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 0])); + expect(client._initMsg).to.have.been.called; + }); + + it('should support Plain authentication with a very long username and password', function () { + client._rfbCredentials = { username: 'a'.repeat(300), password: 'a'.repeat(300) }; + // VeNCrypt version + client._sock._websocket._receiveData(new Uint8Array([0, 2])); + expect(client._sock).to.have.sent(new Uint8Array([0, 2])); + // Server ACK. + client._sock._websocket._receiveData(new Uint8Array([0])); + // Subtype list. + client._sock._websocket._receiveData(new Uint8Array([1, 0, 0, 1, 0])); + + const expectedResponse = []; + push32(expectedResponse, 256); // Chosen subtype. + push32(expectedResponse, client._rfbCredentials.username.length); + push32(expectedResponse, client._rfbCredentials.password.length); + pushString(expectedResponse, client._rfbCredentials.username); + pushString(expectedResponse, client._rfbCredentials.password); + expect(client._sock).to.have.sent(new Uint8Array(expectedResponse)); + + client._initMsg = sinon.spy(); + client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 0])); + expect(client._initMsg).to.have.been.called; + }); + }); }); describe('SecurityResult', function () {