Просмотр исходного кода

Support for RFB 3.8 handshake.

Joel Martin 15 лет назад
Родитель
Сommit
ef764d3b9b
2 измененных файлов с 70 добавлено и 17 удалено
  1. 1 1
      include/base64.js
  2. 69 16
      vnc.js

+ 1 - 1
include/base64.js

@@ -101,7 +101,7 @@ decode: function (data, offset) {
     var data_length = data.indexOf('=') - offset;
     var data_length = data.indexOf('=') - offset;
     if (data_length < 0) data_length = data.length - offset;
     if (data_length < 0) data_length = data.length - offset;
 
 
-    var result_length = (data_length >> 2) * 3 + ((data.length - offset) % 4 - 1);
+    var result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5);
     var result = new Array(result_length);
     var result = new Array(result_length);
 
 
     // Convert one by one.
     // Convert one by one.

+ 69 - 16
vnc.js

@@ -21,6 +21,12 @@ Array.prototype.shift32 = function () {
            (this.shift() <<  8) +
            (this.shift() <<  8) +
            (this.shift()      );
            (this.shift()      );
 }
 }
+Array.prototype.get32 = function (off) {
+    return (this[off    ] << 24) +
+           (this[off + 1] << 16) +
+           (this[off + 2] <<  8) +
+           (this[off + 3]      );
+}
 Array.prototype.push32 = function (num) {
 Array.prototype.push32 = function (num) {
     this.push((num >> 24) & 0xFF,
     this.push((num >> 24) & 0xFF,
               (num >> 16) & 0xFF,
               (num >> 16) & 0xFF,
@@ -85,7 +91,9 @@ ws        : null,  // Web Socket object
 sendID    : null,
 sendID    : null,
 use_seq   : false,
 use_seq   : false,
 
 
-version   : "RFB 003.003\n",
+max_version : 3.8,
+version   : 0,
+auth_scheme : '',
 state     : 'disconnected',
 state     : 'disconnected',
 cuttext   : 'none', // ServerCutText wait state
 cuttext   : 'none', // ServerCutText wait state
 ct_length : 0,
 ct_length : 0,
@@ -115,28 +123,68 @@ rre_chunk : 100,
 init_msg: function () {
 init_msg: function () {
     console.log(">> init_msg");
     console.log(">> init_msg");
 
 
+    //console.log("RQ (" + RQ.length + ") " + RQ);
+
     switch (RFB.state) {
     switch (RFB.state) {
 
 
     case 'ProtocolVersion' :
     case 'ProtocolVersion' :
-        if (RQ.length != 12) {
-            updateStatus('failed', "Disconnected: invalid RFB protocol version received");
+        if (RQ.length < 12) {
+            RFB.updateState('failed', "Disconnected: invalid RFB protocol version received");
+            return;
+        }
+        var server_version = RQ.shiftStr(12).substr(0,11);
+        console.log("Server ProtocolVersion: " + server_version);
+        if ((server_version == "RFB 003.003") || (RFB.max_version == 3.3)) {
+            RFB.version = 3.3;
+            var verstr = "RFB 003.003";
+            RFB.send_string(verstr + "\n");
+            RFB.updateState('Security', "Sent ProtocolVersion: " + verstr);
+        } else if (server_version == "RFB 003.008") {
+            RFB.version = 3.8;
+            var verstr = "RFB 003.008";
+            RFB.send_string(verstr + "\n");
+            RFB.updateState('Security', "Sent ProtocolVersion: " + verstr);
+        } else {
+            RFB.updateState('failed', "Invalid server version " + server_version);
             return;
             return;
         }
         }
-        var server_version = RQ.shiftStr(12);
-        console.log("Server ProtocolVersion: " + server_version.substr(0,11));
-        RFB.send_string(RFB.version);
-        RFB.updateState('Authentication', "Sent ProtocolVersion: " + RFB.version.substr(0,11));
         break;
         break;
 
 
-    case 'Authentication' :
-        if (RQ.length < 4) {
-            RFB.updateState('reset', "Invalid auth frame");
-            return;
+    case 'Security' :
+        if (RFB.version == 3.3) {
+            if (RQ.length < 4) {
+                RFB.updateState('reset', "Invalid security frame");
+                return;
+            }
+            RFB.auth_scheme = RQ.shift32();
+            console.log("auth_scheme: " + RFB.auth_scheme);
+        } else if (RFB.version == 3.8) {
+            var num_types = RQ.shift8();
+            if (num_types == 0) {
+                var strlen = RQ.shift32();
+                var reason = RQ.shiftStr(strlen);
+                RFB.updateState('failed', "Disconnected: security failure: " + reason);
+                return;
+            }
+            var types = RQ.shiftBytes(num_types);
+            if ((types[0] != 1) && (types[0] != 2)) {
+                RFB.updateState('failed', "Disconnected: invalid security type list: " + types);
+                return;
+            }
+            RFB.auth_scheme = types[0];
+            RFB.send_array([RFB.auth_scheme]);
         }
         }
-        var scheme = RQ.shift32();
-        console.log("Auth scheme: " + scheme);
-        switch (scheme) {
+        RFB.updateState('Authentication', "Authenticating using scheme: " + RFB.auth_scheme);
+        // Fall through
+
+    case 'Authentication' :
+        console.log("Security auth scheme: " + RFB.auth_scheme);
+        switch (RFB.auth_scheme) {
             case 0:  // connection failed
             case 0:  // connection failed
+                if (RQ.length < 4) {
+                    console.log("   waiting for auth reason bytes");
+                    return;
+                }
                 var strlen = RQ.shift32();
                 var strlen = RQ.shift32();
                 var reason = RQ.shiftStr(strlen);
                 var reason = RQ.shiftStr(strlen);
                 RFB.updateState('failed', "Disconnected: auth failure: " + reason);
                 RFB.updateState('failed', "Disconnected: auth failure: " + reason);
@@ -146,17 +194,22 @@ init_msg: function () {
                 RFB.updateState('ServerInitialisation');
                 RFB.updateState('ServerInitialisation');
                 break;
                 break;
             case 2:  // VNC authentication
             case 2:  // VNC authentication
+                if (RQ.length < 16) {
+                    console.log("   waiting for auth challenge bytes");
+                    return;
+                }
                 var challenge = RQ.shiftBytes(16);
                 var challenge = RQ.shiftBytes(16);
                 console.log("Password: " + RFB.password);
                 console.log("Password: " + RFB.password);
-                console.log("Challenge: " + challenge + "(" + challenge.length + ")");
+                console.log("Challenge: " + challenge + " (" + challenge.length + ")");
                 passwd = RFB.passwdTwiddle(RFB.password);
                 passwd = RFB.passwdTwiddle(RFB.password);
                 response = des(passwd, challenge, 1);
                 response = des(passwd, challenge, 1);
+                console.log("Response: " + response + " (" + response.length + ")");
 
 
                 RFB.send_array(response);
                 RFB.send_array(response);
                 RFB.updateState('SecurityResult');
                 RFB.updateState('SecurityResult');
                 break;
                 break;
             default:
             default:
-                RFB.updateState('failed', "Disconnected: unsupported auth scheme " + scheme);
+                RFB.updateState('failed', "Disconnected: unsupported auth scheme: " + RFB.auth_scheme);
                 return;
                 return;
         }
         }
         break;
         break;