Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/socks5.py
Show First 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | def __init__(self, cmd, atyp, addr, port, username, password): | ||||
self.cmd = cmd # Command (one of Command.*) | self.cmd = cmd # Command (one of Command.*) | ||||
self.atyp = atyp # Address type (one of AddressType.*) | self.atyp = atyp # Address type (one of AddressType.*) | ||||
self.addr = addr # Address | self.addr = addr # Address | ||||
self.port = port # Port to connect to | self.port = port # Port to connect to | ||||
self.username = username | self.username = username | ||||
self.password = password | self.password = password | ||||
def __repr__(self): | def __repr__(self): | ||||
return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % (self.cmd, self.atyp, self.addr, self.port, self.username, self.password) | return 'Socks5Command({},{},{},{},{},{})'.format( | ||||
self.cmd, self.atyp, self.addr, self.port, self.username, self.password) | |||||
class Socks5Connection(): | class Socks5Connection(): | ||||
def __init__(self, serv, conn, peer): | def __init__(self, serv, conn, peer): | ||||
self.serv = serv | self.serv = serv | ||||
self.conn = conn | self.conn = conn | ||||
self.peer = peer | self.peer = peer | ||||
def handle(self): | def handle(self): | ||||
"""Handle socks5 request according to RFC192.""" | """Handle socks5 request according to RFC192.""" | ||||
try: | try: | ||||
# Verify socks version | # Verify socks version | ||||
ver = recvall(self.conn, 1)[0] | ver = recvall(self.conn, 1)[0] | ||||
if ver != 0x05: | if ver != 0x05: | ||||
raise IOError('Invalid socks version %i' % ver) | raise IOError('Invalid socks version {}'.format(ver)) | ||||
# Choose authentication method | # Choose authentication method | ||||
nmethods = recvall(self.conn, 1)[0] | nmethods = recvall(self.conn, 1)[0] | ||||
methods = bytearray(recvall(self.conn, nmethods)) | methods = bytearray(recvall(self.conn, nmethods)) | ||||
method = None | method = None | ||||
if 0x02 in methods and self.serv.conf.auth: | if 0x02 in methods and self.serv.conf.auth: | ||||
method = 0x02 # username/password | method = 0x02 # username/password | ||||
elif 0x00 in methods and self.serv.conf.unauth: | elif 0x00 in methods and self.serv.conf.unauth: | ||||
method = 0x00 # unauthenticated | method = 0x00 # unauthenticated | ||||
if method is None: | if method is None: | ||||
raise IOError('No supported authentication method was offered') | raise IOError('No supported authentication method was offered') | ||||
# Send response | # Send response | ||||
self.conn.sendall(bytearray([0x05, method])) | self.conn.sendall(bytearray([0x05, method])) | ||||
# Read authentication (optional) | # Read authentication (optional) | ||||
username = None | username = None | ||||
password = None | password = None | ||||
if method == 0x02: | if method == 0x02: | ||||
ver = recvall(self.conn, 1)[0] | ver = recvall(self.conn, 1)[0] | ||||
if ver != 0x01: | if ver != 0x01: | ||||
raise IOError('Invalid auth packet version %i' % ver) | raise IOError('Invalid auth packet version {}'.format(ver)) | ||||
ulen = recvall(self.conn, 1)[0] | ulen = recvall(self.conn, 1)[0] | ||||
username = str(recvall(self.conn, ulen)) | username = str(recvall(self.conn, ulen)) | ||||
plen = recvall(self.conn, 1)[0] | plen = recvall(self.conn, 1)[0] | ||||
password = str(recvall(self.conn, plen)) | password = str(recvall(self.conn, plen)) | ||||
# Send authentication response | # Send authentication response | ||||
self.conn.sendall(bytearray([0x01, 0x00])) | self.conn.sendall(bytearray([0x01, 0x00])) | ||||
# Read connect request | # Read connect request | ||||
ver, cmd, _, atyp = recvall(self.conn, 4) | ver, cmd, _, atyp = recvall(self.conn, 4) | ||||
if ver != 0x05: | if ver != 0x05: | ||||
raise IOError( | raise IOError( | ||||
'Invalid socks version %i in connect request' % ver) | 'Invalid socks version {} in connect request'.format(ver)) | ||||
if cmd != Command.CONNECT: | if cmd != Command.CONNECT: | ||||
raise IOError('Unhandled command %i in connect request' % cmd) | raise IOError( | ||||
'Unhandled command {} in connect request'.format(cmd)) | |||||
if atyp == AddressType.IPV4: | if atyp == AddressType.IPV4: | ||||
addr = recvall(self.conn, 4) | addr = recvall(self.conn, 4) | ||||
elif atyp == AddressType.DOMAINNAME: | elif atyp == AddressType.DOMAINNAME: | ||||
n = recvall(self.conn, 1)[0] | n = recvall(self.conn, 1)[0] | ||||
addr = recvall(self.conn, n) | addr = recvall(self.conn, n) | ||||
elif atyp == AddressType.IPV6: | elif atyp == AddressType.IPV6: | ||||
addr = recvall(self.conn, 16) | addr = recvall(self.conn, 16) | ||||
else: | else: | ||||
raise IOError('Unknown address type %i' % atyp) | raise IOError('Unknown address type {}'.format(atyp)) | ||||
port_hi, port_lo = recvall(self.conn, 2) | port_hi, port_lo = recvall(self.conn, 2) | ||||
port = (port_hi << 8) | port_lo | port = (port_hi << 8) | port_lo | ||||
# Send dummy response | # Send dummy response | ||||
self.conn.sendall( | self.conn.sendall( | ||||
bytearray([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) | bytearray([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) | ||||
cmdin = Socks5Command(cmd, atyp, addr, port, username, password) | cmdin = Socks5Command(cmd, atyp, addr, port, username, password) | ||||
self.serv.queue.put(cmdin) | self.serv.queue.put(cmdin) | ||||
logger.info('Proxy: %s', cmdin) | logger.info('Proxy: {}'.format(cmdin)) | ||||
# Fall through to disconnect | # Fall through to disconnect | ||||
except Exception as e: | except Exception as e: | ||||
logger.exception("socks5 request handling failed.") | logger.exception("socks5 request handling failed.") | ||||
self.serv.queue.put(e) | self.serv.queue.put(e) | ||||
finally: | finally: | ||||
self.conn.close() | self.conn.close() | ||||
Show All 34 Lines |