Commit 49578da4 authored by Joel Martin's avatar Joel Martin

sync with websockify

Pull in websockify 1669139
parent c95456c0
...@@ -172,7 +172,10 @@ function decode_message(data) { ...@@ -172,7 +172,10 @@ function decode_message(data) {
//Util.Debug(">> decode_message: " + data); //Util.Debug(">> decode_message: " + data);
if (mode === 'binary') { if (mode === 'binary') {
// push arraybuffer values onto the end // push arraybuffer values onto the end
rQ.push.apply(rQ, (new Uint8Array(data))); var u8 = new Uint8Array(data);
for (var i = 0; i < u8.length; i++) {
rQ.push(u8[i]);
}
} else { } else {
// base64 decode and concat to the end // base64 decode and concat to the end
rQ = rQ.concat(Base64.decode(data, 0)); rQ = rQ.concat(Base64.decode(data, 0));
......
...@@ -240,32 +240,33 @@ Sec-WebSocket-Accept: %s\r ...@@ -240,32 +240,33 @@ Sec-WebSocket-Accept: %s\r
os.dup2(os.open(os.devnull, os.O_RDWR), sys.stderr.fileno()) os.dup2(os.open(os.devnull, os.O_RDWR), sys.stderr.fileno())
@staticmethod @staticmethod
def unmask(buf, f): def unmask(buf, hlen, plen):
pstart = f['hlen'] + 4 pstart = hlen + 4
pend = pstart + f['length'] pend = pstart + plen
if numpy: if numpy:
b = c = s2b('') b = c = s2b('')
if f['length'] >= 4: if plen >= 4:
mask = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'), mask = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'),
offset=f['hlen'], count=1) offset=hlen, count=1)
data = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'), data = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'),
offset=pstart, count=int(f['length'] / 4)) offset=pstart, count=int(plen / 4))
#b = numpy.bitwise_xor(data, mask).data #b = numpy.bitwise_xor(data, mask).data
b = numpy.bitwise_xor(data, mask).tostring() b = numpy.bitwise_xor(data, mask).tostring()
if f['length'] % 4: if plen % 4:
#print("Partial unmask") #print("Partial unmask")
mask = numpy.frombuffer(buf, dtype=numpy.dtype('B'), mask = numpy.frombuffer(buf, dtype=numpy.dtype('B'),
offset=f['hlen'], count=(f['length'] % 4)) offset=hlen, count=(plen % 4))
data = numpy.frombuffer(buf, dtype=numpy.dtype('B'), data = numpy.frombuffer(buf, dtype=numpy.dtype('B'),
offset=pend - (f['length'] % 4), offset=pend - (plen % 4),
count=(f['length'] % 4)) count=(plen % 4))
c = numpy.bitwise_xor(data, mask).tostring() c = numpy.bitwise_xor(data, mask).tostring()
return b + c return b + c
else: else:
# Slower fallback # Slower fallback
mask = buf[hlen:hlen+4]
data = array.array('B') data = array.array('B')
mask = s2a(f['mask']) mask = s2a(mask)
data.fromstring(buf[pstart:pend]) data.fromstring(buf[pstart:pend])
for i in range(len(data)): for i in range(len(data)):
data[i] ^= mask[i % 4] data[i] ^= mask[i % 4]
...@@ -304,7 +305,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -304,7 +305,7 @@ Sec-WebSocket-Accept: %s\r
Returns: Returns:
{'fin' : 0_or_1, {'fin' : 0_or_1,
'opcode' : number, 'opcode' : number,
'mask' : 32_bit_number, 'masked' : boolean,
'hlen' : header_bytes_number, 'hlen' : header_bytes_number,
'length' : payload_bytes_number, 'length' : payload_bytes_number,
'payload' : decoded_buffer, 'payload' : decoded_buffer,
...@@ -315,7 +316,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -315,7 +316,7 @@ Sec-WebSocket-Accept: %s\r
f = {'fin' : 0, f = {'fin' : 0,
'opcode' : 0, 'opcode' : 0,
'mask' : 0, 'masked' : False,
'hlen' : 2, 'hlen' : 2,
'length' : 0, 'length' : 0,
'payload' : None, 'payload' : None,
...@@ -332,7 +333,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -332,7 +333,7 @@ Sec-WebSocket-Accept: %s\r
b1, b2 = unpack_from(">BB", buf) b1, b2 = unpack_from(">BB", buf)
f['opcode'] = b1 & 0x0f f['opcode'] = b1 & 0x0f
f['fin'] = (b1 & 0x80) >> 7 f['fin'] = (b1 & 0x80) >> 7
has_mask = (b2 & 0x80) >> 7 f['masked'] = (b2 & 0x80) >> 7
f['length'] = b2 & 0x7f f['length'] = b2 & 0x7f
...@@ -347,7 +348,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -347,7 +348,7 @@ Sec-WebSocket-Accept: %s\r
return f # Incomplete frame header return f # Incomplete frame header
(f['length'],) = unpack_from('>xxQ', buf) (f['length'],) = unpack_from('>xxQ', buf)
full_len = f['hlen'] + has_mask * 4 + f['length'] full_len = f['hlen'] + f['masked'] * 4 + f['length']
if blen < full_len: # Incomplete frame if blen < full_len: # Incomplete frame
return f # Incomplete frame header return f # Incomplete frame header
...@@ -356,13 +357,13 @@ Sec-WebSocket-Accept: %s\r ...@@ -356,13 +357,13 @@ Sec-WebSocket-Accept: %s\r
f['left'] = blen - full_len f['left'] = blen - full_len
# Process 1 frame # Process 1 frame
if has_mask: if f['masked']:
# unmask payload # unmask payload
f['mask'] = buf[f['hlen']:f['hlen']+4] f['payload'] = WebSocketServer.unmask(buf, f['hlen'],
f['payload'] = WebSocketServer.unmask(buf, f) f['length'])
else: else:
print("Unmasked frame: %s" % repr(buf)) print("Unmasked frame: %s" % repr(buf))
f['payload'] = buf[(f['hlen'] + has_mask * 4):full_len] f['payload'] = buf[(f['hlen'] + f['masked'] * 4):full_len]
if base64 and f['opcode'] in [1, 2]: if base64 and f['opcode'] in [1, 2]:
try: try:
...@@ -389,6 +390,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -389,6 +390,7 @@ Sec-WebSocket-Accept: %s\r
end = buf.find(s2b('\xff')) end = buf.find(s2b('\xff'))
return {'payload': b64decode(buf[1:end]), return {'payload': b64decode(buf[1:end]),
'hlen': 1, 'hlen': 1,
'masked': False,
'length': end - 1, 'length': end - 1,
'left': len(buf) - (end + 1)} 'left': len(buf) - (end + 1)}
...@@ -456,7 +458,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -456,7 +458,7 @@ Sec-WebSocket-Accept: %s\r
if self.rec: if self.rec:
self.rec.write("%s,\n" % self.rec.write("%s,\n" %
repr("{%s{" % tdelta repr("{%s{" % tdelta
+ encbuf[lenhead:-lentail])) + encbuf[lenhead:len(encbuf)-lentail]))
self.send_parts.append(encbuf) self.send_parts.append(encbuf)
...@@ -536,8 +538,14 @@ Sec-WebSocket-Accept: %s\r ...@@ -536,8 +538,14 @@ Sec-WebSocket-Accept: %s\r
if self.rec: if self.rec:
start = frame['hlen'] start = frame['hlen']
end = frame['hlen'] + frame['length'] end = frame['hlen'] + frame['length']
if frame['masked']:
recbuf = WebSocketServer.unmask(buf, frame['hlen'],
frame['length'])
else:
recbuf = buf[frame['hlen']:frame['hlen'] +
frame['length']]
self.rec.write("%s,\n" % self.rec.write("%s,\n" %
repr("}%s}" % tdelta + buf[start:end])) repr("}%s}" % tdelta + recbuf))
bufs.append(frame['payload']) bufs.append(frame['payload'])
...@@ -779,6 +787,10 @@ Sec-WebSocket-Accept: %s\r ...@@ -779,6 +787,10 @@ Sec-WebSocket-Accept: %s\r
self.handler_id) self.handler_id)
self.msg("opening record file: %s" % fname) self.msg("opening record file: %s" % fname)
self.rec = open(fname, 'w+') self.rec = open(fname, 'w+')
encoding = "binary"
if self.base64: encoding = "base64"
self.rec.write("var VNC_frame_encoding = '%s';\n"
% encoding)
self.rec.write("var VNC_frame_data = [\n") self.rec.write("var VNC_frame_data = [\n")
self.ws_connection = True self.ws_connection = True
...@@ -800,7 +812,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -800,7 +812,7 @@ Sec-WebSocket-Accept: %s\r
self.msg(traceback.format_exc()) self.msg(traceback.format_exc())
finally: finally:
if self.rec: if self.rec:
self.rec.write("'EOF']\n") self.rec.write("'EOF'];\n")
self.rec.close() self.rec.close()
if self.client and self.client != startsock: if self.client and self.client != startsock:
......
...@@ -11,7 +11,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates ...@@ -11,7 +11,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
''' '''
import socket, optparse, time, os, sys, subprocess import signal, socket, optparse, time, os, sys, subprocess
from select import select from select import select
import websocket import websocket
try: from urllib.parse import parse_qs, urlparse try: from urllib.parse import parse_qs, urlparse
...@@ -87,7 +87,7 @@ Traffic Legend: ...@@ -87,7 +87,7 @@ Traffic Legend:
self.wrap_times.append(time.time()) self.wrap_times.append(time.time())
self.wrap_times.pop(0) self.wrap_times.pop(0)
self.cmd = subprocess.Popen( self.cmd = subprocess.Popen(
self.wrap_cmd, env=os.environ) self.wrap_cmd, env=os.environ, preexec_fn=_subprocess_setup)
self.spawn_message = True self.spawn_message = True
def started(self): def started(self):
...@@ -144,7 +144,7 @@ Traffic Legend: ...@@ -144,7 +144,7 @@ Traffic Legend:
else: else:
self.run_wrap_cmd() self.run_wrap_cmd()
# #
# Routines above this point are run in the master listener # Routines above this point are run in the master listener
# process. # process.
# #
...@@ -165,13 +165,13 @@ Traffic Legend: ...@@ -165,13 +165,13 @@ Traffic Legend:
# Connect to the target # Connect to the target
if self.wrap_cmd: if self.wrap_cmd:
msg = "connecting to command: %s" % (" ".join(self.wrap_cmd), self.target_port) msg = "connecting to command: '%s' (port %s)" % (" ".join(self.wrap_cmd), self.target_port)
elif self.unix_target: elif self.unix_target:
msg = "connecting to unix socket: %s" % self.unix_target msg = "connecting to unix socket: %s" % self.unix_target
else: else:
msg = "connecting to: %s:%s" % ( msg = "connecting to: %s:%s" % (
self.target_host, self.target_port) self.target_host, self.target_port)
if self.ssl_target: if self.ssl_target:
msg += " (using SSL)" msg += " (using SSL)"
self.msg(msg) self.msg(msg)
...@@ -291,6 +291,13 @@ Traffic Legend: ...@@ -291,6 +291,13 @@ Traffic Legend:
self.target_host, self.target_port)) self.target_host, self.target_port))
raise self.CClose(closed['code'], closed['reason']) raise self.CClose(closed['code'], closed['reason'])
def _subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
# non-Python successfulbprocesses expect.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def websockify_init(): def websockify_init():
usage = "\n %prog [options]" usage = "\n %prog [options]"
usage += " [source_addr:]source_port [target_addr:target_port]" usage += " [source_addr:]source_port [target_addr:target_port]"
...@@ -338,7 +345,7 @@ def websockify_init(): ...@@ -338,7 +345,7 @@ def websockify_init():
(opts, args) = parser.parse_args() (opts, args) = parser.parse_args()
# Sanity checks # Sanity checks
if len(args) < 2 and not opts.target_cfg: if len(args) < 2 and not (opts.target_cfg or opts.unix_target):
parser.error("Too few arguments") parser.error("Too few arguments")
if sys.argv.count('--'): if sys.argv.count('--'):
opts.wrap_cmd = args[1:] opts.wrap_cmd = args[1:]
...@@ -349,7 +356,7 @@ def websockify_init(): ...@@ -349,7 +356,7 @@ def websockify_init():
if not websocket.ssl and opts.ssl_target: if not websocket.ssl and opts.ssl_target:
parser.error("SSL target requested and Python SSL module not loaded."); parser.error("SSL target requested and Python SSL module not loaded.");
if opts.ssl_only and not os.path.exists(opts.cert): if opts.ssl_only and not os.path.exists(opts.cert):
parser.error("SSL only and %s not found" % opts.cert) parser.error("SSL only and %s not found" % opts.cert)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment