diff --git a/vnc.html b/vnc.html index d69e40de..4454eba2 100644 --- a/vnc.html +++ b/vnc.html @@ -65,7 +65,7 @@ RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash"); } else { WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf"; - RFB.force_copy = true; + RFB.use_seq = true; RFB.updateState('disconnected', 'Disconnected'); } } diff --git a/vnc.js b/vnc.js index 653374eb..5fbaa031 100644 --- a/vnc.js +++ b/vnc.js @@ -83,7 +83,7 @@ RFB = { ws : null, // Web Socket object sendID : null, -force_copy : false, +use_seq : false, version : "RFB 003.003\n", state : 'disconnected', @@ -647,6 +647,84 @@ clientCutText: function (text) { * Utility routines */ +recv_message: function(e) { + //console.log(">> recv_message"); + RQ = RQ.concat(Base64.decode(e.data, 0)); + + RFB.handle_message(); + //console.log("<< recv_message"); +}, + +recv_message_reorder: function(e) { + //console.log(">> recv_message_reorder"); + + var offset = e.data.indexOf(":") + 1; + var seq_num = parseInt(e.data.substr(0, offset-1)); + if (RQ_seq_num == seq_num) { + RQ = RQ.concat(Base64.decode(e.data, offset)); + RQ_seq_num++; + } else { + console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num); + if (RQ_reorder.length > 20) { + RFB.updateState('failed', "Re-order queue too long"); + } else { + RQ_reorder = RQ_reorder.concat(e.data.substr(0)); + var i = 0; + while (i < RQ_reorder.length) { + var offset = RQ_reorder[i].indexOf(":") + 1; + var seq_num = parseInt(RQ_reorder[i].substr(0, offset-1)); + console.log("Searching reorder list item " + i + ", seq_num " + seq_num); + if (seq_num == RQ_seq_num) { + /* Remove it from reorder queue, decode it and + * add it to the receive queue */ + console.log("Found re-ordered packet seq_num " + seq_num); + RQ = RQ.concat(Base64.decode(RQ_reorder.splice(i, 1)[0], offset)); + RQ_seq_num++; + i = 0; // Start search again for next one + } else { + i++; + } + } + + } + } + + RFB.handle_message(); + //console.log("<< recv_message_reorder"); +}, + +handle_message: function () { + switch (RFB.state) { + case 'disconnected': + console.error("Got data while disconnected"); + break; + case 'reset': + /* close and reset connection */ + RFB.disconnect(); + RFB.init_ws(); + break; + case 'failed': + console.log("Giving up!"); + RFB.disconnect(); + break; + case 'normal': + RFB.normal_msg(); + /* + while (RQ.length > 0) { + if (RFB.normal_msg() && RFB.state == 'normal') { + console.log("More to process"); + } else { + break; + } + } + */ + break; + default: + RFB.init_msg(); + break; + } +}, + send_string: function (str) { //console.log(">> send_string: " + str); RFB.send_array(str.split('').map( @@ -828,74 +906,18 @@ updateState: function(state, statusMsg) { init_ws: function () { console.log(">> init_ws"); - var uri = "ws://" + RFB.host + ":" + RFB.port; + var uri = "ws://" + RFB.host + ":" + RFB.port + "/?b64encode"; + if (RFB.use_seq) { + uri += "&seq_num"; + } console.log("connecting to " + uri); RFB.ws = new WebSocket(uri); - RFB.ws.onmessage = function(e) { - //console.log(">> WebSocket.onmessage"); - var offset = e.data.indexOf(":") + 1; - var seq_num = parseInt(e.data.substr(0, offset-1)); - if (RQ_seq_num == seq_num) { - RQ = RQ.concat(Base64.decode(e.data, offset)); - RQ_seq_num++; - } else { - console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num); - if (RQ_reorder.length > 20) { - RFB.updateState('failed', "Re-order queue too long"); - } else { - RQ_reorder = RQ_reorder.concat(e.data.substr(0)); - var i = 0; - while (i < RQ_reorder.length) { - var offset = RQ_reorder[i].indexOf(":") + 1; - var seq_num = parseInt(RQ_reorder[i].substr(0, offset-1)); - console.log("Searching reorder list item " + i + ", seq_num " + seq_num); - if (seq_num == RQ_seq_num) { - /* Remove it from reorder queue, decode it and - * add it to the receive queue */ - console.log("Found re-ordered packet seq_num " + seq_num); - RQ = RQ.concat(Base64.decode(RQ_reorder.splice(i, 1)[0], offset)); - RQ_seq_num++; - i = 0; // Start search again for next one - } else { - i++; - } - } - - } - } - - switch (RFB.state) { - case 'disconnected': - console.error("WebSocket.onmessage while disconnected"); - break; - case 'reset': - /* close and reset connection */ - RFB.disconnect(); - RFB.init_ws(); - break; - case 'failed': - console.log("Giving up!"); - RFB.disconnect(); - break; - case 'normal': - RFB.normal_msg(); - /* - while (RQ.length > 0) { - if (RFB.normal_msg() && RFB.state == 'normal') { - console.log("More to process"); - } else { - break; - } - } - */ - break; - default: - RFB.init_msg(); - break; - } - //console.log("<< WebSocket.onmessage"); - }; + if (RFB.use_seq) { + RFB.ws.onmessage = RFB.recv_message_reorder; + } else { + RFB.ws.onmessage = RFB.recv_message; + } RFB.ws.onopen = function(e) { console.log(">> WebSocket.onopen"); RFB.updateState('ProtocolVersion', "Starting VNC handshake"); diff --git a/wsproxy.py b/wsproxy.py index 4d8ff3fc..b47cb9b1 100755 --- a/wsproxy.py +++ b/wsproxy.py @@ -1,11 +1,12 @@ #!/usr/bin/python -import sys, os, socket, time, traceback +import sys, os, socket, time, traceback, re from base64 import b64encode, b64decode from select import select buffer_size = 65536 send_seq = 0 +client_settings = {} server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r Upgrade: WebSocket\r @@ -32,21 +33,27 @@ Traffic Legend: def do_handshake(client): + global client_settings handshake = client.recv(1024) - print "Handshake [%s]" % handshake + #print "Handshake [%s]" % handshake if handshake.startswith(""): - print "Sending:", policy_response + print "Sending flash policy response" client.send(policy_response) client.close() return False - #handshake = client.recv(1024) - #if len(handshake) == 0: - # raise Exception("Policy exchange failed") - #print "Handshake [%s]" % handshake req_lines = handshake.split("\r\n") _, path, _ = req_lines[0].split(" ") _, origin = req_lines[4].split(" ") _, host = req_lines[3].split(" ") + + # Parse settings from the path + cvars = path.partition('?')[2].partition('#')[0].split('&') + for cvar in [c for c in cvars if c]: + name, _, value = cvar.partition('=') + client_settings[name] = value and value or True + + print "client_settings:", client_settings + client.send(server_handshake % (origin, host, path)) return True @@ -76,7 +83,7 @@ def proxy(client, target): if tqueue and target in outs: #print "Target send: %s" % repr(tqueue[0]) - log.write("Target send: %s\n" % map(ord, tqueue[0])) + ##log.write("Target send: %s\n" % map(ord, tqueue[0])) dat = tqueue.pop(0) sent = target.send(dat) if sent == len(dat): @@ -90,25 +97,28 @@ def proxy(client, target): sent = client.send(dat) if sent == len(dat): traffic("<") - log.write("Client send: %s\n" % repr(dat)) + ##log.write("Client send: %s\n" % repr(dat)) else: cqueue.insert(0, dat[sent:]) traffic("<.") - log.write("Client send partial: %s\n" % repr(dat[0:send])) + ##log.write("Client send partial: %s\n" % repr(dat[0:send])) if target in ins: buf = target.recv(buffer_size) if len(buf) == 0: raise Exception("Target closed") - #enc = b64encode(buf) - #chksum = sum([ord(c) for c in enc]) - #cqueue.append("\x00^" + str(chksum) + "@" + enc + "$\xff") + ##log.write("Target recv (%d): %s\n" % (len(buf), map(ord, buf))) - cqueue.append("\x00%d:%s\xff" % (send_seq, b64encode(buf))) - send_seq += 1 + if client_settings.get("b64encode"): + buf = b64encode(buf) + + if client_settings.get("seq_num"): + cqueue.append("\x00%d:%s\xff" % (send_seq, buf)) + send_seq += 1 + else: + cqueue.append("\x00%s\xff" % buf) - log.write("Target recv (%d): %s\n" % (len(buf), map(ord, buf))) traffic("{") if client in ins: @@ -117,7 +127,7 @@ def proxy(client, target): if buf[-1] == "\xff": traffic("}") - log.write("Client recv (%d): %s\n" % (len(buf), repr(buf))) + ##log.write("Client recv (%d): %s\n" % (len(buf), repr(buf))) if cpartial: tqueue.extend(decode(cpartial + buf)) cpartial = "" @@ -125,7 +135,7 @@ def proxy(client, target): tqueue.extend(decode(buf)) else: traffic("}.") - log.write("Client recv partial (%d): %s\n" % (len(buf), repr(buf))) + ##log.write("Client recv partial (%d): %s\n" % (len(buf), repr(buf))) cpartial = cpartial + buf @@ -157,7 +167,7 @@ def start_server(listen_port, target_host, target_port): if tsock: tsock.close() if __name__ == '__main__': - log = open("ws.log", 'w') + ##log = open("ws.log", 'w') try: if len(sys.argv) != 4: raise listen_port = int(sys.argv[1])