diff --git a/rfb_notes b/rfb_notes
new file mode 100644
index 00000000..643e16c0
--- /dev/null
+++ b/rfb_notes
@@ -0,0 +1,147 @@
+5.1.1 ProtocolVersion: 12, 12 bytes
+
+ - Sent by server, max supported
+ 12 ascii - "RFB 003.008\n"
+ - Response by client, version to use
+ 12 ascii - "RFB 003.003\n"
+
+5.1.2 Authentication: >=4, [16, 4] bytes
+
+ - Sent by server
+ CARD32 - authentication-scheme
+ 0 - connection failed
+ CARD32 - length
+ length - reason
+ 1 - no authentication
+
+ 2 - VNC authentication
+ 16 CARD8 - challenge (random bytes)
+
+ - Response by client (if VNC authentication)
+ 16 CARD8 - client encrypts the challenge with DES, using user
+ password as key, sends resulting 16 byte response
+
+ - Response by server (if VNC authentication)
+ CARD32 - 0 - OK
+ 1 - failed
+ 2 - too-many
+
+5.1.3 ClientInitialisation: 1 byte
+ - Sent by client
+ CARD8 - shared-flag, 0 exclusive, non-zero shared
+
+5.1.4 ServerInitialisation: >=24 bytes
+ - Sent by server
+ CARD16 - framebuffer-width
+ CARD16 - framebuffer-height
+ 16 byte PIXEL_FORMAT - server-pixel-format
+ CARD8 - bits-per-pixel
+ CARD8 - depth
+ CARD8 - big-endian-flag, non-zero is big endian
+ CARD8 - true-color-flag, non-zero then next 6 apply
+ CARD16 - red-max
+ CARD16 - green-max
+ CARD16 - blue-max
+ CARD8 - red-shift
+ CARD8 - green-shift
+ CARD8 - blue-shift
+ 3 bytes - padding
+ CARD32 - name-length
+
+ CARD8[length] - name-string
+
+
+
+Client to Server Messages:
+
+5.2.1 SetPixelFormat: 20 bytes
+ CARD8: 0 - message-type
+ ...
+
+5.2.2 FixColourMapEntries: >=6 bytes
+ CARD8: 1 - message-type
+ ...
+
+5.2.3 SetEncodings: >=8 bytes
+ CARD8: 2 - message-type
+ CARD8 - padding
+ CARD16 - numer-of-encodings
+
+ CARD32 - encoding-type in preference order
+ 0 - raw
+ 1 - copy-rectangle
+ 2 - RRE
+ 4 - CoRRE
+ 5 - hextile
+
+5.2.4 FramebufferUpdateRequest (10 bytes)
+ CARD8: 3 - message-type
+ CARD8 - incremental (0 for full-update, non-zero for incremental)
+ CARD16 - x-position
+ CARD16 - y-position
+ CARD16 - width
+ CARD16 - height
+
+
+5.2.5 KeyEvent: 8 bytes
+ CARD8: 4 - message-type
+ CARD8 - down-flag
+ 2 bytes - padding
+ CARD32 - key (X-Windows keysym values)
+
+5.2.6 PointerEvent: 6 bytes
+ CARD8: 5 - message-type
+ CARD8 - button-mask
+ CARD16 - x-position
+ CARD16 - y-position
+
+5.2.7 ClientCutText: >=9 bytes
+ CARD8: 6 - message-type
+ ...
+
+
+Server to Client Messages:
+
+5.3.1 FramebufferUpdate
+ CARD8: 0 - message-type
+ 1 byte - padding
+ CARD16 - number-of-rectangles
+
+ CARD16 - x-position
+ CARD16 - y-position
+ CARD16 - width
+ CARD16 - height
+ CARD16 - encoding-type:
+ 0 - raw
+ 1 - copy rectangle
+ 2 - RRE
+ 4 - CoRRE
+ 5 - hextile
+
+ raw:
+ - width x height pixel values
+
+ copy rectangle:
+ CARD16 - src-x-position
+ CARD16 - src-y-position
+
+ RRE:
+ CARD32 - N number-of-subrectangles
+ Nxd bytes - background-pixel-value (d bits-per-pixel)
+
+ ...
+
+5.3.2 SetColourMapEntries (no support)
+ CARD8: 1 - message-type
+ ...
+
+5.3.3 Bell
+ CARD8: 2 - message-type
+
+5.3.4 ServerCutText
+ CARD8: 3 - message-type
+
+
+
+
+
diff --git a/vnc.html b/vnc.html
new file mode 100644
index 00000000..196e4183
--- /dev/null
+++ b/vnc.html
@@ -0,0 +1,38 @@
+
+
+
+
+ VNC Window:
+
+
+
+
+ Debug:
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vnc.js b/vnc.js
new file mode 100644
index 00000000..7a565aba
--- /dev/null
+++ b/vnc.js
@@ -0,0 +1,339 @@
+debug("here0");
+var ws = null;
+var vnc_host = '';
+var vnc_port = 5900;
+var rfb_state = 'ProtocolVersion';
+var rfb_shared = 1;
+var fb_width = 0;
+var fb_height = 0;
+var fb_name = "";
+
+function card8(num) {
+ return String.fromCharCode(num);
+}
+String.prototype.card8 = function (pos) {
+ return this.charCodeAt(pos);
+}
+
+function card16(num) {
+ return String.fromCharCode(num >> 8) +
+ String.fromCharCode(num & 0xFF);
+}
+String.prototype.card16 = function (pos) {
+ debug("card16 0: " + this.charCodeAt(pos));
+ debug("card16 1: " + this.charCodeAt(pos+1));
+ return (this.charCodeAt(pos) << 8) +
+ (this.charCodeAt(pos+1) );
+}
+
+function card32(num) {
+ return String.fromCharCode( num >> 24) +
+ String.fromCharCode((num >> 16) & 0xFF) +
+ String.fromCharCode((num >> 8) & 0xFF) +
+ String.fromCharCode( num & 0xFF);
+}
+String.prototype.card32 = function (pos) {
+ debug("card32 0: " + this.charCodeAt(pos));
+ debug("card32 1: " + this.charCodeAt(pos+1));
+ debug("card32 2: " + this.charCodeAt(pos+2));
+ debug("card32 3: " + this.charCodeAt(pos+3));
+ return (this.charCodeAt(pos) << 24) +
+ (this.charCodeAt(pos+1) << 16) +
+ (this.charCodeAt(pos+2) << 8) +
+ (this.charCodeAt(pos+3) );
+}
+
+function debug(str) {
+ cell = $('debug');
+ cell.innerHTML += str + "
";
+}
+
+
+/*
+ * Server message handlers
+ */
+
+/* RFB/VNC initialisation */
+function rfb_init_msg(data) {
+ debug(">> rfb_init_msg");
+ switch (rfb_state) {
+
+ case 'ProtocolVersion' :
+ debug("ProtocolVersion: " + data)
+ if (data.length != 12) {
+ debug("Invalid protocol version from server");
+ rfb_state = 'reset';
+ return;
+ }
+ ws.send("RFB 003.003\n");
+ rfb_state = 'Authentication';
+ break;
+
+ case 'Authentication' :
+ debug("Authentication")
+ if (data.length != 4) {
+ debug("Invalid auth scheme");
+ rfb_state = 'reset';
+ return;
+ }
+ var scheme = data.card32(0);
+ debug("Auth scheme: " + scheme);
+ switch (scheme) {
+ case 0: // connection failed
+ var strlen = data.card32(4);
+ var reason = data.substr(8, strlen);
+ debug("auth failed: " + reason);
+ rfb_state = "reset";
+ return;
+ case 1: // no authentication
+ ws.send(card8(rfb_shared)); // ClientInitialisation
+ rfb_state = "ServerInitialisation";
+ break;
+ case 2: // VNC authentication
+ var challenge = data.substr(4, 16);
+ // TODO:
+ //var crypt = des(challenge, password);
+ //ws.send(crypt);
+ rfb_state = "Authentication-VNC";
+ break;
+ }
+ break;
+
+ case 'Authentication-VNC' :
+ debug("Authentication-VNC")
+ if (data.length != 4) {
+ debug("Invalid server auth response");
+ rfb_state = 'reset';
+ return;
+ }
+ var resp = data.card32(0);
+ switch (resp) {
+ case 0: // OK
+ debug("Authentication OK");
+ break;
+ case 1: // failed
+ debug("Authentication failed");
+ rfb_state = "reset";
+ return;
+ case 2: // too-many
+ debug("Too many authentication attempts");
+ rfb_state = "reset";
+ return;
+ }
+ ws.send(card8(rfb_shared)); // ClientInitialisation
+ rfb_state = "ServerInitialisation";
+ break;
+
+ case 'ServerInitialisation' :
+ debug("ServerInitialisation")
+ if (data.length < 24) {
+ debug("Invalid server initialisation");
+ rfb_state = 'reset';
+ return;
+ }
+ fb_width = data.card16(0);
+ fb_height = data.card16(2);
+ var name_length = data.card32(20);
+ fb_name = data.substr(24, name_length);
+ debug("Screen size: " + fb_width + "x" + fb_height);
+ debug("Name: " + fb_name);
+ rfb_state = 'normal';
+ break;
+ }
+ debug("<< rfb_init_msg");
+}
+
+/* Normal RFB/VNC messages */
+function rfb_msg(data) {
+ debug(">> rfb_msg");
+ var msg_type = data.card8(0);
+ switch (msg_type) {
+ case 0: // FramebufferUpdate
+ debug("FramebufferUpdate");
+ break;
+ case 1: // SetColourMapEntries
+ debug("SetColourMapEntries");
+ break;
+ case 2: // Bell
+ debug("Bell");
+ break;
+ case 3: // ServerCutText
+ debug("ServerCutText");
+ break;
+ default:
+ debug("Unknown server message type: " + msg_type);
+ break;
+ }
+ debug("<< rfb_msg");
+}
+
+/*
+ * Client message routines
+ */
+
+function setPixelFormat() {
+}
+
+function fixColourMapEntries() {
+}
+
+function setEncodings() {
+}
+
+function fbUpdateRequest() {
+}
+
+function keyEvent() {
+}
+
+function pointerEvent() {
+}
+
+function clientCutText() {
+}
+
+
+/*
+ * Setup routines
+ */
+
+function _init_ws() {
+ debug(">> _init_ws");
+ var uri = "ws://" + vnc_host + ":" + vnc_port;
+ debug("connecting to " + uri);
+ ws = new WebSocket(uri);
+ ws.onmessage = function(e) {
+ debug(">> onmessage");
+ if (rfb_state != 'normal') {
+ rfb_init_msg(e.data);
+ } else {
+ rfb_msg(e.data);
+ }
+ if (rfb_state == 'reset') {
+ /* close and reset connection */
+ ws.close();
+ _init_ws();
+ }
+ debug("<< onmessage");
+ };
+ ws.onopen = function(e) {
+ debug(">> onopen");
+ rfb_state = "ProtocolVersion";
+ debug("<< onopen");
+ };
+ ws.onclose = function(e) {
+ debug(">> onclose");
+ rfb_state = "closed";
+ debug("<< onclose");
+ }
+ debug("<< _init_ws");
+}
+
+function init_ws(host, port) {
+ debug(">> init_ws");
+ vnc_host = host;
+ vnc_port = port;
+ if (ws) {
+ ws.close();
+ }
+ _init_ws();
+ debug("<< init_ws");
+
+}
+
+/*
+function draw() {
+ var canvas = document.getElementById('vnc');
+
+ if (! canvas.getContext) return;
+
+ var ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = "rgb(50,50,50)";
+ ctx.fillRect(0, 0, 800, 600);
+
+ var img = new Image();
+ img.src = "head_ani2.gif"
+
+ ctx.drawImage(img, 10, 10);
+
+ ctx.drawImage(canvas, 20, 20, 30, 30, 70, 70, 30, 30);
+}
+
+
+function draw2() {
+ var canvas = document.getElementById('tutorial');
+
+ if (! canvas.getContext) return;
+
+ var ctx = canvas.getContext('2d');
+
+ roundedRect(ctx,12,12,150,150,15);
+ roundedRect(ctx,19,19,150,150,9);
+ roundedRect(ctx,53,53,49,33,10);
+ roundedRect(ctx,53,119,49,16,6);
+ roundedRect(ctx,135,53,49,33,10);
+ roundedRect(ctx,135,119,25,49,10);
+
+ ctx.beginPath();
+ ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,true);
+ ctx.lineTo(31,37);
+ ctx.fill();
+ for(var i=0;i<8;i++){
+ ctx.fillRect(51+i*16,35,4,4);
+ }
+ for(i=0;i<6;i++){
+ ctx.fillRect(115,51+i*16,4,4);
+ }
+ for(i=0;i<8;i++){
+ ctx.fillRect(51+i*16,99,4,4);
+ }
+ ctx.beginPath();
+ ctx.moveTo(83,116);
+ ctx.lineTo(83,102);
+ ctx.bezierCurveTo(83,94,89,88,97,88);
+ ctx.bezierCurveTo(105,88,111,94,111,102);
+ ctx.lineTo(111,116);
+ ctx.lineTo(106.333,111.333);
+ ctx.lineTo(101.666,116);
+ ctx.lineTo(97,111.333);
+ ctx.lineTo(92.333,116);
+ ctx.lineTo(87.666,111.333);
+ ctx.lineTo(83,116);
+ ctx.fill();
+ ctx.fillStyle = "white";
+ ctx.beginPath();
+ ctx.moveTo(91,96);
+ ctx.bezierCurveTo(88,96,87,99,87,101);
+ ctx.bezierCurveTo(87,103,88,106,91,106);
+ ctx.bezierCurveTo(94,106,95,103,95,101);
+ ctx.bezierCurveTo(95,99,94,96,91,96);
+ ctx.moveTo(103,96);
+ ctx.bezierCurveTo(100,96,99,99,99,101);
+ ctx.bezierCurveTo(99,103,100,106,103,106);
+ ctx.bezierCurveTo(106,106,107,103,107,101);
+ ctx.bezierCurveTo(107,99,106,96,103,96);
+ ctx.fill();
+ ctx.fillStyle = "black";
+ ctx.beginPath();
+ ctx.arc(101,102,2,0,Math.PI*2,true);
+ ctx.fill();
+ ctx.beginPath();
+ ctx.arc(89,102,2,0,Math.PI*2,true);
+ ctx.fill();
+}
+function roundedRect(ctx,x,y,width,height,radius){
+ ctx.beginPath();
+ ctx.moveTo(x,y+radius);
+ ctx.lineTo(x,y+height-radius);
+ ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
+ ctx.lineTo(x+width-radius,y+height);
+ ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
+ ctx.lineTo(x+width,y+radius);
+ ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
+ ctx.lineTo(x+radius,y);
+ ctx.quadraticCurveTo(x,y,x,y+radius);
+ ctx.stroke();
+}
+*/
+debug("here10");
diff --git a/wsproxy.py b/wsproxy.py
index 3d147801..b6c90e77 100755
--- a/wsproxy.py
+++ b/wsproxy.py
@@ -20,6 +20,10 @@ def handshake(client):
_, host = req_lines[3].split(" ")
client.send(server_handshake % (origin, host, path))
+def traffic(token="."):
+ sys.stdout.write(token)
+ sys.stdout.flush()
+
def proxy(client, target):
cqueue = []
tqueue = []
@@ -33,23 +37,28 @@ def proxy(client, target):
buf = client.recv(1024)
if len(buf) == 0: raise Exception("Client closed")
tqueue.append(buf[1:-1])
- print "Client recv: %s (%d)" % (buf[1:-1], len(buf))
+ #print "Client recv: %s (%d)" % (buf[1:-1], len(buf))
+ traffic("}")
if target in ins:
buf = target.recv(1024)
if len(buf) == 0: raise Exception("Target closed")
cqueue.append("\x00" + buf + "\xff")
- print "Target recv: %s (%d)" % (buf, len(buf))
+ #print "Target recv: %s (%d)" % (buf, len(buf))
+ traffic("{")
if cqueue and client in outs:
while cqueue:
- print "Client send: %s" % cqueue[0]
+ #print "Client send: %s" % cqueue[0]
client.send(cqueue.pop(0))
+ traffic("<")
if tqueue and target in outs:
while tqueue:
- print "Target send: %s" % tqueue[0]
+ #print "Target send: %s" % tqueue[0]
+ sys.stdout.flush()
target.send(tqueue.pop(0))
+ traffic(">")
def start_server(listen_port, target_host, target_port):
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)