aboutsummaryrefslogtreecommitdiff
path: root/qa/rpc-tests/test_framework/socks5.py
diff options
context:
space:
mode:
authorJohn Newbery <john@johnnewbery.com>2017-03-08 15:56:30 -0500
committerJohn Newbery <john@johnnewbery.com>2017-03-20 10:40:31 -0400
commit00902c48cdc5d6a531abfd279fd8e7779cf0a0b8 (patch)
tree41891484a478a7478937fe4a12b63e6c7f31799a /qa/rpc-tests/test_framework/socks5.py
parentd34995a7bac6ed20ce42aa00c6252b900786e649 (diff)
Rename qa directory to test
Diffstat (limited to 'qa/rpc-tests/test_framework/socks5.py')
-rw-r--r--qa/rpc-tests/test_framework/socks5.py160
1 files changed, 0 insertions, 160 deletions
diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py
deleted file mode 100644
index dd7624d454..0000000000
--- a/qa/rpc-tests/test_framework/socks5.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Dummy Socks5 server for testing."""
-
-import socket, threading, queue
-import traceback, sys
-import logging
-
-logger = logging.getLogger("TestFramework.socks5")
-
-### Protocol constants
-class Command:
- CONNECT = 0x01
-
-class AddressType:
- IPV4 = 0x01
- DOMAINNAME = 0x03
- IPV6 = 0x04
-
-### Utility functions
-def recvall(s, n):
- """Receive n bytes from a socket, or fail."""
- rv = bytearray()
- while n > 0:
- d = s.recv(n)
- if not d:
- raise IOError('Unexpected end of stream')
- rv.extend(d)
- n -= len(d)
- return rv
-
-### Implementation classes
-class Socks5Configuration(object):
- """Proxy configuration."""
- def __init__(self):
- self.addr = None # Bind address (must be set)
- self.af = socket.AF_INET # Bind address family
- self.unauth = False # Support unauthenticated
- self.auth = False # Support authentication
-
-class Socks5Command(object):
- """Information about an incoming socks5 command."""
- def __init__(self, cmd, atyp, addr, port, username, password):
- self.cmd = cmd # Command (one of Command.*)
- self.atyp = atyp # Address type (one of AddressType.*)
- self.addr = addr # Address
- self.port = port # Port to connect to
- self.username = username
- self.password = password
- def __repr__(self):
- return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % (self.cmd, self.atyp, self.addr, self.port, self.username, self.password)
-
-class Socks5Connection(object):
- def __init__(self, serv, conn, peer):
- self.serv = serv
- self.conn = conn
- self.peer = peer
-
- def handle(self):
- """Handle socks5 request according to RFC192."""
- try:
- # Verify socks version
- ver = recvall(self.conn, 1)[0]
- if ver != 0x05:
- raise IOError('Invalid socks version %i' % ver)
- # Choose authentication method
- nmethods = recvall(self.conn, 1)[0]
- methods = bytearray(recvall(self.conn, nmethods))
- method = None
- if 0x02 in methods and self.serv.conf.auth:
- method = 0x02 # username/password
- elif 0x00 in methods and self.serv.conf.unauth:
- method = 0x00 # unauthenticated
- if method is None:
- raise IOError('No supported authentication method was offered')
- # Send response
- self.conn.sendall(bytearray([0x05, method]))
- # Read authentication (optional)
- username = None
- password = None
- if method == 0x02:
- ver = recvall(self.conn, 1)[0]
- if ver != 0x01:
- raise IOError('Invalid auth packet version %i' % ver)
- ulen = recvall(self.conn, 1)[0]
- username = str(recvall(self.conn, ulen))
- plen = recvall(self.conn, 1)[0]
- password = str(recvall(self.conn, plen))
- # Send authentication response
- self.conn.sendall(bytearray([0x01, 0x00]))
-
- # Read connect request
- (ver,cmd,rsv,atyp) = recvall(self.conn, 4)
- if ver != 0x05:
- raise IOError('Invalid socks version %i in connect request' % ver)
- if cmd != Command.CONNECT:
- raise IOError('Unhandled command %i in connect request' % cmd)
-
- if atyp == AddressType.IPV4:
- addr = recvall(self.conn, 4)
- elif atyp == AddressType.DOMAINNAME:
- n = recvall(self.conn, 1)[0]
- addr = recvall(self.conn, n)
- elif atyp == AddressType.IPV6:
- addr = recvall(self.conn, 16)
- else:
- raise IOError('Unknown address type %i' % atyp)
- port_hi,port_lo = recvall(self.conn, 2)
- port = (port_hi << 8) | port_lo
-
- # Send dummy response
- self.conn.sendall(bytearray([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
-
- cmdin = Socks5Command(cmd, atyp, addr, port, username, password)
- self.serv.queue.put(cmdin)
- logger.info('Proxy: %s', cmdin)
- # Fall through to disconnect
- except Exception as e:
- logger.exception("socks5 request handling failed.")
- self.serv.queue.put(e)
- finally:
- self.conn.close()
-
-class Socks5Server(object):
- def __init__(self, conf):
- self.conf = conf
- self.s = socket.socket(conf.af)
- self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.s.bind(conf.addr)
- self.s.listen(5)
- self.running = False
- self.thread = None
- self.queue = queue.Queue() # report connections and exceptions to client
-
- def run(self):
- while self.running:
- (sockconn, peer) = self.s.accept()
- if self.running:
- conn = Socks5Connection(self, sockconn, peer)
- thread = threading.Thread(None, conn.handle)
- thread.daemon = True
- thread.start()
-
- def start(self):
- assert(not self.running)
- self.running = True
- self.thread = threading.Thread(None, self.run)
- self.thread.daemon = True
- self.thread.start()
-
- def stop(self):
- self.running = False
- # connect to self to end run loop
- s = socket.socket(self.conf.af)
- s.connect(self.conf.addr)
- s.close()
- self.thread.join()
-