Fix security failure reason handling of slow data

Things would break if the security result and security reason did
not arrive in the same WebSocket message.
This commit is contained in:
Pierre Ossman 2019-02-15 10:24:41 +01:00
parent c13df5ae67
commit 3bb15d4aa0
1 changed files with 27 additions and 32 deletions

View File

@ -853,7 +853,10 @@ export default class RFB extends EventTargetMixin {
if (this._sock.rQwait("security type", num_types, 1)) { return false; }
if (num_types === 0) {
return this._handle_security_failure("no security types");
this._rfb_init_state = "SecurityReason";
this._security_context = "no security types";
this._security_status = 1;
return this._init_msg();
}
const types = this._sock.rQshiftBytes(num_types);
@ -878,6 +881,13 @@ export default class RFB extends EventTargetMixin {
// Server decides
if (this._sock.rQwait("security scheme", 4)) { return false; }
this._rfb_auth_scheme = this._sock.rQshift32();
if (this._rfb_auth_scheme == 0) {
this._rfb_init_state = "SecurityReason";
this._security_context = "authentication scheme";
this._security_status = 1;
return this._init_msg();
}
}
this._rfb_init_state = 'Authentication';
@ -886,28 +896,7 @@ export default class RFB extends EventTargetMixin {
return this._init_msg(); // jump to authentication
}
/*
* Get the security failure reason if sent from the server and
* send the 'securityfailure' event.
*
* - The optional parameter context can be used to add some extra
* context to the log output.
*
* - The optional parameter security_result_status can be used to
* add a custom status code to the event.
*/
_handle_security_failure(context, security_result_status) {
if (typeof context === 'undefined') {
context = "";
} else {
context = " on " + context;
}
if (typeof security_result_status === 'undefined') {
security_result_status = 1; // fail
}
_handle_security_reason() {
if (this._sock.rQwait("reason length", 4)) {
return false;
}
@ -915,23 +904,26 @@ export default class RFB extends EventTargetMixin {
let reason = "";
if (strlen > 0) {
if (this._sock.rQwait("reason", strlen, 8)) { return false; }
if (this._sock.rQwait("reason", strlen, 4)) { return false; }
reason = this._sock.rQshiftStr(strlen);
}
if (reason !== "") {
this.dispatchEvent(new CustomEvent(
"securityfailure",
{ detail: { status: security_result_status, reason: reason } }));
{ detail: { status: this._security_status,
reason: reason } }));
return this._fail("Security negotiation failed" + context +
return this._fail("Security negotiation failed on " +
this._security_context +
" (reason: " + reason + ")");
} else {
this.dispatchEvent(new CustomEvent(
"securityfailure",
{ detail: { status: security_result_status } }));
{ detail: { status: this._security_status } }));
return this._fail("Security negotiation failed" + context);
return this._fail("Security negotiation failed on " +
this._security_context);
}
}
@ -1077,9 +1069,6 @@ export default class RFB extends EventTargetMixin {
_negotiate_authentication() {
switch (this._rfb_auth_scheme) {
case 0: // connection failed
return this._handle_security_failure("authentication scheme");
case 1: // no auth
if (this._rfb_version >= 3.8) {
this._rfb_init_state = 'SecurityResult';
@ -1114,7 +1103,10 @@ export default class RFB extends EventTargetMixin {
return this._init_msg();
} else {
if (this._rfb_version >= 3.8) {
return this._handle_security_failure("security result", status);
this._rfb_init_state = "SecurityReason";
this._security_context = "security result";
this._security_status = status;
return this._init_msg();
} else {
this.dispatchEvent(new CustomEvent(
"securityfailure",
@ -1283,6 +1275,9 @@ export default class RFB extends EventTargetMixin {
case 'SecurityResult':
return this._handle_security_result();
case 'SecurityReason':
return this._handle_security_reason();
case 'ClientInitialisation':
this._sock.send([this._shared ? 1 : 0]); // ClientInitialisation
this._rfb_init_state = 'ServerInitialisation';