Browse Source

Support the "NOTUNNEL" tunnel type for TightVNC

Previously, tight auth was supported without any support for tunnels,
even the no-op tunnel.  No, the no-op tunnel type is supported.
Solly Ross 11 years ago
parent
commit
95eb681bbb
2 changed files with 80 additions and 10 deletions
  1. 39 10
      include/rfb.js
  2. 41 0
      include/util.js

+ 39 - 10
include/rfb.js

@@ -322,6 +322,7 @@ init_vars = function() {
     FBU.zlibs        = []; // TIGHT zlib encoders
     mouse_buttonMask = 0;
     mouse_arr        = [];
+    rfb_tightvnc     = false;
 
     // Clear the per connection encoding stats
     for (i=0; i < encodings.length; i+=1) {
@@ -775,23 +776,51 @@ init_msg = function() {
                 updateState('SecurityResult');
                 return;
             case 16: // TightVNC Security Type
-                if (ws.rQwait("num tunnels", 4)) { return false; }
-                var numTunnels = ws.rQshift32();
-                //console.log("Number of tunnels: "+numTunnels);
-
-                rfb_tightvnc = true;
+                if (!rfb_tightvnc) {
+                    // we haven't been through this before, so assume
+                    // we need to check for tunnel support
+                    if (ws.rQwait("num tunnels", 4)) { return false; }
+                    var numTunnels = ws.rQshift32();
+                    //console.log("Number of tunnels: "+numTunnels);
+
+                    rfb_tightvnc = true;
+
+                    var clientSupportedTunnelTypes = {
+                        0: { vender: 'TGHT', signature: 'NOTUNNEL' }
+                    };
+
+                    if (numTunnels > 0) {
+                        var serverSupportedTunnelTypes = {}
+                        // receive tunnel capabilities
+                        for (var i = 0; i < numTunnels; i++) {
+                            if (ws.rQwait("tunnel " + i.toString() + " capability", 16)) { return false; }
+
+                            var cap_code = ws.rQshift32();
+                            var cap_vendor = ws.rQshiftStr(4);
+                            var cap_signature = ws.rQshiftStr(8);
+                            serverSupportedTunnelTypes[cap_code] = { vendor: cap_vendor, signature: cap_signature };
+                        }
 
-                if (numTunnels != 0)
-                {
-                    fail("Protocol requested tunnels, not currently supported. numTunnels: " + numTunnels);
-                    return;
-                }
+                        // choose an auth type
+                        for (var cap_code in clientSupportedTunnelTypes) {
+                            if (serverSupportedTunnelTypes[cap_code] != undefined) {
+                                // TODO(directxman12): convert capcode back to U32
+                                ws.send([0,0,0,cap_code]);
+                                return;
+                            }
+                        }
+                        
+                        fail("No supported tunnel types");
+                        return;
+                    }
+                } // otherwise, we've dealt with tunnels, so jump right into auth
 
                 var clientSupportedTypes = {
                     'STDVNOAUTH__': 1,
                     'STDVVNCAUTH_': 2
                 };
 
+
                 var serverSupportedTypes = [];
 
                 if (ws.rQwait("sub auth count", 4)) { return false; }

+ 41 - 0
include/util.js

@@ -84,6 +84,47 @@ if (!Array.prototype.indexOf)
   };
 }
 
+// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+if (!Object.keys) {
+  Object.keys = (function () {
+    'use strict';
+    var hasOwnProperty = Object.prototype.hasOwnProperty,
+        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
+        dontEnums = [
+          'toString',
+          'toLocaleString',
+          'valueOf',
+          'hasOwnProperty',
+          'isPrototypeOf',
+          'propertyIsEnumerable',
+          'constructor'
+        ],
+        dontEnumsLength = dontEnums.length;
+
+    return function (obj) {
+      if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
+        throw new TypeError('Object.keys called on non-object');
+      }
+
+      var result = [], prop, i;
+
+      for (prop in obj) {
+        if (hasOwnProperty.call(obj, prop)) {
+          result.push(prop);
+        }
+      }
+
+      if (hasDontEnumBug) {
+        for (i = 0; i < dontEnumsLength; i++) {
+          if (hasOwnProperty.call(obj, dontEnums[i])) {
+            result.push(dontEnums[i]);
+          }
+        }
+      }
+      return result;
+    };
+  }());
+}
 
 // 
 // requestAnimationFrame shim with setTimeout fallback