diff --git a/.gitignore b/.gitignore index 92260b8..e8ba463 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ venv build + +__pycache__/ +*.pyc diff --git a/README.md b/README.md index 0ce8470..e542ebe 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,44 @@ -RPIVOT - reverse socks 4 proxy for penetration tests -=================== - +# RPIVOT - Reverse SOCKS4 Proxy for Penetration Tests RPIVOT allows to tunnel traffic into internal network via socks 4. It works like ssh dynamic port forwarding but in the opposite direction. +--- ----------- - - -Description -------------- +## Description -This tool is Python 2.6-2.7 compatible and has no dependencies beyond the standard library. It has client-server architecture. Just run the client on the machine you want to tunnel the traffic through. Server should be started on pentester's machine and listen to incoming connections from the client. +This tool is **Python 3.12+** compatible and has no dependencies beyond the standard library. It has client-server architecture. Just run the client on the machine you want to tunnel the traffic through. Server should be started on pentester's machine and listen to incoming connections from the client. Works on Kali Linux, Solaris 10, Windows, Mac OS. +> **Note**: This tool was originally Python 2.6-2.7 compatible. It has been updated to work with modern Python 3.12+. -Usage example -------------- +--- + +## Usage Example Start server listener on port 9999, which creates a socks 4 proxy on 127.0.0.1:1080 upon connection from client: -`python server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127.0.0.1 --proxy-port 1080` +```bash +python3 server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127.0.0.1 --proxy-port 1080 +``` Connect to the server: -`python client.py --server-ip --server-port 9999` +```bash +python3 client.py --server-ip --server-port 9999 +``` To pivot through an NTLM proxy: -`python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd` +```bash +python3 client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd +``` Pass-the-hash is supported: -`python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --hashes 9b9850751be2515c8231e5189015bbe6:49ef7638d69a01f26d96ed673bf50c45` +```bash +python3 client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --hashes 9b9850751be2515c8231e5189015bbe6:49ef7638d69a01f26d96ed673bf50c45 +``` You can use `proxychains` to tunnel traffic through socks proxy. @@ -49,19 +54,20 @@ socks4 127.0.0.1 1080 Using single zip file mode: -``` +```bash zip rpivot.zip -r *.py ./ntlm_auth/ -python rpivot.zip server -python rpivot.zip client +python3 rpivot.zip server +python3 rpivot.zip client ``` Pivot and have fun: -`proxychains ` +```bash +proxychains +``` -Pre-built Windows client binary available in release section. +--- -Author ------- +## Author Artem Kondratenko https://twitter.com/artkond diff --git a/client.py b/client.py index ce35cf5..069040f 100644 --- a/client.py +++ b/client.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import logging import logging.handlers @@ -19,7 +19,7 @@ def key_by_value(my_dict, value): - for k, v in my_dict.iteritems(): + for k, v in my_dict.items(): if v == value: return k return None @@ -74,17 +74,19 @@ def run(self): try: time.sleep(relay.delay) - logger.debug("Active channels: {0}. Pending Channels {1}".format(self.channel.keys(), self.establishing_dict.values())) + logger.debug("Active channels: {0}. Pending Channels {1}".format(list(self.channel.keys()), list(self.establishing_dict.values()))) inputready, outputready, exceptready = select.select(self.input_list, self.establishing_dict.keys(), [], 15) except KeyboardInterrupt: logger.info('SIGINT received. Closing relay and exiting') self.send_remote_cmd(self.bc_sock, relay.CLOSE_RELAY) self.shutdown() - except select.error as (code, msg): - logger.debug('Select error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + except select.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) + logger.debug('Select error on select. Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) self.shutdown() - except socket.error as (code, msg): - logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) + logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) self.shutdown() for sock in outputready: @@ -92,9 +94,11 @@ def run(self): logger.debug('Establishing connection with channel id {0}'.format(channel_id)) try: sock.recv(0) - except socket.error as (code, err_msg): + except socket.error as e: + code = e.args[0] if e.args else 0 + err_msg = e.args[1] if len(e.args) > 1 else str(e) if code == errno.ECONNREFUSED or code == errno.ETIMEDOUT: - logger.debug('Connection {0}'.format(errno.errorcode[code])) + logger.debug('Connection {0}'.format(errno.errorcode.get(code, code))) if sock in inputready: inputready.remove(sock) @@ -131,7 +135,7 @@ def run(self): self.manage_forward_socket(self.selected_input_socket) def handle_remote_cmd(self, data): - cmd = data[0] + cmd = data[0:1] logger.debug('Received cmd data from remote side. Cmd: {0}'.format(relay.cmd_names[cmd])) if cmd == relay.CHANNEL_CLOSE_CMD: channel_id = unpack('= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on receiving tlv message from remote side. Exiting') - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) raise relay.RelayError return channel_id, data @@ -188,7 +193,7 @@ def manage_remote_socket(self, sock): elif channel_id in self.channel: relay_to_sock = self.channel[channel_id] logger.debug('Got data to relay from remote side. Channel id {0}. Data length: {1}'.format(channel_id, len(data))) - logger.debug('Data contents: {0}'.format(data.encode('hex'))) + logger.debug('Data contents: {0}'.format(data.hex())) self.relay(data, relay_to_sock) else: logger.debug('Relay from socket {0} with channel {1} not possible. Channel does not exist'.format(sock, channel_id)) @@ -206,9 +211,10 @@ def manage_forward_socket(self, sock): #logger.debug('Readable socket {0} with channel id {1}'.format(sock, channel_id)) try: data = sock.recv(relay.buffer_size) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on receiving data from socket {0} with channel id {1}'.format(sock, channel_id)) - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) logger.debug('Closing socket {0} with channel id {1}'.format(sock, channel_id)) self.close_forward_connection(sock) return @@ -220,8 +226,8 @@ def manage_forward_socket(self, sock): channel_id = self.id_by_socket[sock] tlv_header = pack(' 1 else str(e) + logger.error('Socket error on sending command to remote side. Code {0}. Msg {1}'.format(code, cmd_err)) def set_channel(self, sock, channel_id): self.channel[channel_id] = sock @@ -267,7 +275,8 @@ def establish_forward_socket(self, channel_id, host, port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(0) sock.connect_ex((host, port)) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug("Caught exception socket.error during establishing forward connection. Code {0}. Msg {1}".format(code, msg)) self.send_remote_cmd(self.bc_sock, relay.FORWARD_CONNECTION_FAILURE, channel_id) return @@ -279,9 +288,10 @@ def relay(self, data, to_socket): return try: to_socket.send(data) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on relaying data to socket {0}'.format(to_socket)) - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) if to_socket == self.bc_sock: raise relay.RelayError else: @@ -295,19 +305,19 @@ def relay(self, data, to_socket): class NtlmProxyContext(object): - negotiate_request = '''CONNECT {0}:{1} HTTP/1.1 -User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 -Proxy-Connection: keep-alive -Connection: keep-alive -Proxy-Authorization: NTLM {2} - + negotiate_request = '''CONNECT {0}:{1} HTTP/1.1\r +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0\r +Proxy-Connection: keep-alive\r +Connection: keep-alive\r +Proxy-Authorization: NTLM {2}\r +\r ''' - authenticate_request = '''CONNECT {0}:{1} HTTP/1.1 -User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 -Proxy-Connection: keep-alive -Connection: keep-alive -Proxy-Authorization: NTLM {2} - + authenticate_request = '''CONNECT {0}:{1} HTTP/1.1\r +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0\r +Proxy-Connection: keep-alive\r +Connection: keep-alive\r +Proxy-Authorization: NTLM {2}\r +\r ''' def __init__(self, sock, proxy_ip, proxy_port, username, domain=None, password=None, nthash=None, lmhash=None): @@ -328,9 +338,10 @@ def connect(self, host_port): resp = None try: self._sock.connect((self._proxy_ip, self._proxy_port)) - self._sock.send(NtlmProxyContext.negotiate_request.format(host, str(port), negotiate_message)) - resp = self._sock.recv(4096) - except socket.error as (code, msg): + self._sock.send(NtlmProxyContext.negotiate_request.format(host, str(port), negotiate_message).encode()) + resp = self._sock.recv(4096).decode('utf-8', errors='replace') + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.error("Caught socket error trying to establish connection to proxy. Code {0}. Msg {1}".format(code, msg)) raise @@ -338,7 +349,7 @@ def connect(self, host_port): chal_msg = NtlmProxyContext.get_challenge(resp) ntlm_context.parse_challenge_message(chal_msg) except TypeError: - logger.error("Couldn't parse proxy challenge. Code {0}. Msg {1}".format(code, msg)) + logger.error("Couldn't parse proxy challenge.") if resp is not None: logger.error("Challenge contents: {0}".format(resp)) else: @@ -354,9 +365,10 @@ def connect(self, host_port): lmhash=self._lmhash).decode() resp = None try: - self._sock.send(NtlmProxyContext.authenticate_request.format(host, str(port), authenticate_message)) - resp = self._sock.recv(4096) - except socket.error as (code, msg): + self._sock.send(NtlmProxyContext.authenticate_request.format(host, str(port), authenticate_message).encode()) + resp = self._sock.recv(4096).decode('utf-8', errors='replace') + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.error("Caught socket error trying to send challenge response connection to proxy. Code {0}. Msg {1}".format(code, msg)) self._sock.close() raise @@ -421,7 +433,7 @@ def main(): cmd_options = parser.parse_args()[0] if cmd_options.server_ip is None: - print 'Server IP required' + print('Server IP required') sys.exit() logger = logging.getLogger('root') logger.setLevel(logging.DEBUG) @@ -466,7 +478,8 @@ def main(): bc_sock = ntlm_con bc_sock.connect((backconnect_host, backconnect_port)) break - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.info('Unable to connect to {0} port: {1}. Caught socket error trying to establish connection with RPIVOT server. Code {2}. Msg {3}'.format(cmd_options.server_ip, cmd_options.server_port, code, msg)) logger.info('Retrying') time.sleep(5) @@ -479,7 +492,8 @@ def main(): bc_sock.close() time.sleep(5) continue - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.error("Caught socket error trying to establish connection with RPIVOT server. Code {0}. Msg {1}".format(code, msg)) bc_sock.close() time.sleep(5) @@ -488,9 +502,10 @@ def main(): socks_relayer = SocksRelay(bc_sock) try: socks_relayer.run() - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception in socks_relayer.run(). Restarting relay') - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) bc_sock.close() continue time.sleep(10) diff --git a/ntlm_auth/compute_hash.py b/ntlm_auth/compute_hash.py index ed1cdba..7f08a87 100644 --- a/ntlm_auth/compute_hash.py +++ b/ntlm_auth/compute_hash.py @@ -32,7 +32,7 @@ def _lmowfv1(password, lmhash): # fix the password length to 14 bytes if lmhash is not None: - return lmhash.decode('hex') + return bytes.fromhex(lmhash) password = password.upper() lm_pw = password[0:14] @@ -60,7 +60,7 @@ def _ntowfv1(password, nthash): :return digest: An NT hash of the password supplied """ if nthash is not None: - return nthash.decode('hex') + return bytes.fromhex(nthash) digest = hashlib.new('md4', password.encode('utf-16le')).digest() return digest @@ -82,4 +82,23 @@ def _ntowfv2(user_name, password, nthash, domain_name): digest = hmac.new(digest, (user_name.upper() + domain_name).encode('utf-16le')).digest() + return digest + +def _ntowfv2(user_name, password, nthash, domain_name): + """ + [MS-NLMP] v28.0 2016-07-14 + + 3.3.2 NTLM v2 Authentication + Same function as NTOWFv2 (and LMOWFv2) in document to create a one way hash of the password. + This combines some extra security features over the v1 calculations used in NTLMv2 auth. + + :param user_name: The user name of the user we are trying to authenticate with + :param password: The password of the user we are trying to authenticate with + :param domain_name: The domain name of the user account we are authenticated with + :return digest: An NT hash of the parameters supplied + """ + digest = _ntowfv1(password, nthash) + digest = hmac.new(digest, (user_name.upper() + domain_name).encode('utf-16le')).digest() + + return digest \ No newline at end of file diff --git a/ntlm_auth/compute_response.py b/ntlm_auth/compute_response.py index ffc4456..3823bcd 100644 --- a/ntlm_auth/compute_response.py +++ b/ntlm_auth/compute_response.py @@ -382,11 +382,7 @@ def _get_channel_bindings_value(server_certificate_hash): channel_bindings_struct_data = gss_channel_bindings.get_data() channel_bindings_hash = hashlib.md5(channel_bindings_struct_data).hexdigest() - try: - cbt_value = bytearray.fromhex(channel_bindings_hash) - except TypeError: - # Work-around for Python 2.6 bug - cbt_value = bytearray.fromhex(unicode(channel_bindings_hash)) + cbt_value = bytes.fromhex(channel_bindings_hash) channel_bindings = bytes(cbt_value) return channel_bindings diff --git a/ntlm_auth/ntlm.py b/ntlm_auth/ntlm.py index c003ad1..2db542a 100644 --- a/ntlm_auth/ntlm.py +++ b/ntlm_auth/ntlm.py @@ -47,7 +47,7 @@ class Ntlm(object): :param ntlm_compatibility: The Lan Manager Compatibility Level to use withe the auth message - Default 3 This is set by an Administrator in the registry key - 'HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel' + 'HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\\\\LmCompatibilityLevel' The values correspond to the following; 0 : LM and NTLMv1 1 : LM, NTLMv1 and NTLMv1 with Extended Session Security diff --git a/ntlm_auth/target_info.py b/ntlm_auth/target_info.py index 5ff8e33..9da9178 100644 --- a/ntlm_auth/target_info.py +++ b/ntlm_auth/target_info.py @@ -8,10 +8,7 @@ """ import struct -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict +from collections import OrderedDict class TargetInfo(object): MSV_AV_EOL = 0x00 diff --git a/ordereddict.py b/ordereddict.py deleted file mode 100644 index 5b0303f..0000000 --- a/ordereddict.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (c) 2009 Raymond Hettinger -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. - -from UserDict import DictMixin - -class OrderedDict(dict, DictMixin): - - def __init__(self, *args, **kwds): - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__end - except AttributeError: - self.clear() - self.update(*args, **kwds) - - def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] - dict.clear(self) - - def __setitem__(self, key, value): - if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev - - def __iter__(self): - end = self.__end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.__end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - if last: - key = reversed(self).next() - else: - key = iter(self).next() - value = self.pop(key) - return key, value - - def __reduce__(self): - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end - inst_dict = vars(self).copy() - self.__map, self.__end = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def keys(self): - return list(self) - - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - if isinstance(other, OrderedDict): - if len(self) != len(other): - return False - for p, q in zip(self.items(), other.items()): - if p != q: - return False - return True - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other diff --git a/relay.py b/relay.py index ab19fe6..f26e3ef 100644 --- a/relay.py +++ b/relay.py @@ -4,28 +4,28 @@ buffer_size = 4096 delay = 0.0001 -socks_server_reply_success = '\x00\x5a\xff\xff\xff\xff\xff\xff' -socks_server_reply_fail = '\x00\x5b\xff\xff\xff\xff\xff\xff' +socks_server_reply_success = b'\x00\x5a\xff\xff\xff\xff\xff\xff' +socks_server_reply_fail = b'\x00\x5b\xff\xff\xff\xff\xff\xff' relay_timeout = 60 -banner = 'RPIVOT' -banner_response = 'TUNNELRDY' +banner = b'RPIVOT' +banner_response = b'TUNNELRDY' COMMAND_CHANNEL = 0 -CHANNEL_CLOSE_CMD = '\xcc' -CHANNEL_OPEN_CMD = '\xdd' -FORWARD_CONNECTION_SUCCESS = '\xee' -FORWARD_CONNECTION_FAILURE = '\xff' -CLOSE_RELAY = '\xc4' -PING_CMD = '\x70' +CHANNEL_CLOSE_CMD = b'\xcc' +CHANNEL_OPEN_CMD = b'\xdd' +FORWARD_CONNECTION_SUCCESS = b'\xee' +FORWARD_CONNECTION_FAILURE = b'\xff' +CLOSE_RELAY = b'\xc4' +PING_CMD = b'\x70' cmd_names = { - '\xcc': 'CHANNEL_CLOSE_CMD', - '\xdd': 'CHANNEL_OPEN_CMD', - '\xee': 'FORWARD_CONNECTION_SUCCESS', - '\xff': 'FORWARD_CONNECTION_FAILURE', - '\xc4': 'CLOSE_RELAY', - '\x70': 'PING_CMD' + b'\xcc': 'CHANNEL_CLOSE_CMD', + b'\xdd': 'CHANNEL_OPEN_CMD', + b'\xee': 'FORWARD_CONNECTION_SUCCESS', + b'\xff': 'FORWARD_CONNECTION_FAILURE', + b'\xc4': 'CLOSE_RELAY', + b'\x70': 'PING_CMD' } @@ -38,7 +38,7 @@ class RelayError(Exception): def recvall(sock, data_len): - buf = '' + buf = b'' while True: buf += sock.recv(data_len - len(buf)) if len(buf) == data_len: diff --git a/server.py b/server.py index de7edd9..41daf9f 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import logging import logging.handlers @@ -36,7 +36,8 @@ def __init__(self, host, port, socket_with_server): try: self.server.bind((host, port)) self.server.listen(2000) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.error('Error binding socks proxy. {0}'.format(msg)) logger.error('Closing relay') socket_with_server.close() @@ -57,7 +58,8 @@ def ping_worker(self): logger.debug('Sending ping') try: self.send_remote_cmd(self.socket_with_server, relay.PING_CMD) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Ping thread got socket exception {0} {1}. Closing socket with remote side'.format(code, msg)) self.socket_with_server.close() return @@ -77,10 +79,11 @@ def main_loop(self): time.sleep(relay.delay) try: - logger.debug("Active channels: {0}".format(self.channel.keys())) + logger.debug("Active channels: {0}".format(list(self.channel.keys()))) inputready, outputready, exceptready = select.select(self.input_list, [], []) - except socket.error as (code, msg): - logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) + logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) return except KeyboardInterrupt: logger.info('SIGINT received. Closing relay and exiting') @@ -138,9 +141,10 @@ def get_channel_data(self, sock): tlv_header = relay.recvall(sock, 4) channel_id, tlv_data_len = unpack('= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on receiving tlv message from remote side. Exiting') - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) raise relay.RelayError return channel_id, data @@ -151,7 +155,7 @@ def manage_remote_socket(self, sock): elif channel_id in self.channel: relay_to_sock = self.channel[channel_id] logger.debug('Got data to relay from remote side. Channel id {0}. Data length: {1}'.format(channel_id, len(data))) - logger.debug('Data contents: {0}'.format(data.encode('hex'))) + logger.debug('Data contents: {0}'.format(data.hex())) self.relay(data, relay_to_sock) else: logger.debug('Relay from socket {0} with channel {1} not possible. Channel does not exist'.format(sock, channel_id)) @@ -160,9 +164,10 @@ def manage_remote_socket(self, sock): def manage_socks_client_socket(self, sock): try: data = sock.recv(relay.buffer_size) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on reading socket {0} with channel id {1}'.format(sock, self.id_by_socket[sock])) - logger.debug('Details: {0}, {1}'.format(errno.errorcode[code], msg)) + logger.debug('Details: {0}, {1}'.format(errno.errorcode.get(code, code), msg)) self.close_socks_connection(sock) return data_len = len(data) @@ -173,12 +178,12 @@ def manage_socks_client_socket(self, sock): channel_id = self.id_by_socket[sock] tlv_header = pack(' 1 else str(e) + logger.error('Socket error on replying SUCCESS to socks client. Code {0}. Msg {1}'.format(code, msg)) logger.debug('Closing client socket and sending channel close cmd to remote side') sock = self.channel[channel_id] self.input_list.remove(sock) @@ -220,8 +227,10 @@ def handle_remote_cmd(self, data): sock = self.channel[channel_id] try: sock.send(relay.socks_server_reply_fail) - except socket.error as (code, msg): - logger.error('Socket error on replying FAILURE to socks client. Code {0}. Msg {0}'.format(code, cmd)) + except socket.error as e: + code = e.args[0] if e.args else 0 + msg = e.args[1] if len(e.args) > 1 else str(e) + logger.error('Socket error on replying FAILURE to socks client. Code {0}. Msg {0}'.format(code, msg)) self.input_list.remove(sock) self.unset_channel(channel_id) try: @@ -255,8 +264,10 @@ def send_remote_cmd(self, sock, cmd, *args): tlv_header = pack(' 1 else str(e) + logger.error('Socket error on sending command to remote side. Code {0}. Msg {1}'.format(code, msg)) raise relay.RelayError def on_accept(self): @@ -277,11 +288,12 @@ def handle_new_socks_connection(self, sock): if len(data) != 9: logger.debug('Error receiving socks header: corrupted header') raise relay.RelayError - if data[-1] != '\x00': + if data[-1:] != b'\x00': logger.debug('Error receiving socks header: corrupted header') raise relay.RelayError - except socket.error as (code, msg): - logger.debug('Error receiving socks header {0} {1}'.format(errno.errorcode[code], msg)) + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) + logger.debug('Error receiving socks header {0} {1}'.format(errno.errorcode.get(code, code), msg)) raise relay.RelayError if len(data) == 0: logger.debug('Socks client prematurely ended connection') @@ -300,7 +312,7 @@ def unset_channel(self, channel_id): del self.channel[channel_id] def generate_new_channel_id(self): - channel_ids = self.channel.keys() + channel_ids = list(self.channel.keys()) while True: rint = random.randint(1, 65535) if rint not in channel_ids: @@ -320,9 +332,10 @@ def relay(self, data, to_socket): return try: to_socket.send(data) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.debug('Exception on relaying data to socket {0}'.format(to_socket)) - logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) + logger.debug('Errno: {0} Msg: {1}'.format(errno.errorcode.get(code, code), msg)) if to_socket == self.socket_with_server: raise relay.RelayError else: @@ -361,14 +374,16 @@ def run_server(host, port): socket_with_remote_side.close() continue socket_with_remote_side.send(relay.banner_response) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.error("Caught socket error trying to establish connection with RPIVOT client. Code {0}. Msg {1}".format(code, msg)) continue try: server = RelayServer(cmd_options.proxy_ip, int(cmd_options.proxy_port), socket_with_remote_side) - except socket.error as (code, msg): + except socket.error as e: + code, msg = e.args if len(e.args) >= 2 else (e.args[0] if e.args else 0, str(e)) logger.info('Error on running relay server. Restarting') continue try: @@ -379,7 +394,7 @@ def run_server(host, port): continue except KeyboardInterrupt: - print "Ctrl C - Stopping server" + print("Ctrl C - Stopping server") sys.exit(1) @@ -422,6 +437,3 @@ def main(): if __name__ == "__main__": main() - - - diff --git a/six.py b/six.py deleted file mode 100644 index 190c023..0000000 --- a/six.py +++ /dev/null @@ -1,868 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.10.0" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 -PY34 = sys.version_info[0:2] >= (3, 4) - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - try: - # This is a bit ugly, but it avoids running this again by - # removing this descriptor. - delattr(obj.__class__, self.name) - except AttributeError: - pass - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("intern", "__builtin__", "sys"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), - MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), -] -# Add windows specific modules. -if sys.platform == "win32": - _moved_attributes += [ - MovedModule("winreg", "_winreg"), - ] - -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "urllib", "urllib.parse"), - MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), - MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), - MovedAttribute("uses_params", "urlparse", "urllib.parse"), - MovedAttribute("uses_query", "urlparse", "urllib.parse"), - MovedAttribute("uses_relative", "urlparse", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - def create_unbound_method(func, cls): - return func - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - def create_unbound_method(func, cls): - return types.MethodType(func, None, cls) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) - - viewkeys = operator.methodcaller("keys") - - viewvalues = operator.methodcaller("values") - - viewitems = operator.methodcaller("items") -else: - def iterkeys(d, **kw): - return d.iterkeys(**kw) - - def itervalues(d, **kw): - return d.itervalues(**kw) - - def iteritems(d, **kw): - return d.iteritems(**kw) - - def iterlists(d, **kw): - return d.iterlists(**kw) - - viewkeys = operator.methodcaller("viewkeys") - - viewvalues = operator.methodcaller("viewvalues") - - viewitems = operator.methodcaller("viewitems") - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - - def u(s): - return s - unichr = chr - import struct - int2byte = struct.Struct(">B").pack - del struct - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO - _assertCountEqual = "assertCountEqual" - if sys.version_info[1] <= 1: - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" - else: - _assertRaisesRegex = "assertRaisesRegex" - _assertRegex = "assertRegex" -else: - def b(s): - return s - # Workaround for standalone backslash - - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - - def byte2int(bs): - return ord(bs[0]) - - def indexbytes(buf, i): - return ord(buf[i]) - iterbytes = functools.partial(itertools.imap, ord) - import StringIO - StringIO = BytesIO = StringIO.StringIO - _assertCountEqual = "assertItemsEqual" - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -def assertCountEqual(self, *args, **kwargs): - return getattr(self, _assertCountEqual)(*args, **kwargs) - - -def assertRaisesRegex(self, *args, **kwargs): - return getattr(self, _assertRaisesRegex)(*args, **kwargs) - - -def assertRegex(self, *args, **kwargs): - return getattr(self, _assertRegex)(*args, **kwargs) - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - def reraise(tp, value, tb=None): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - raise value from from_value -""") -else: - def raise_from(value, from_value): - raise value - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) -if sys.version_info[:2] < (3, 3): - _print = print_ - - def print_(*args, **kwargs): - fp = kwargs.get("file", sys.stdout) - flush = kwargs.pop("flush", False) - _print(*args, **kwargs) - if flush and fp is not None: - fp.flush() - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - def wrapper(f): - f = functools.wraps(wrapped, assigned, updated)(f) - f.__wrapped__ = wrapped - return f - return wrapper -else: - wraps = functools.wraps - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(meta): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -def python_2_unicode_compatible(klass): - """ - A decorator that defines __unicode__ and __str__ methods under Python 2. - Under Python 3 it does nothing. - - To support Python 2 and 3 with a single code base, define a __str__ method - returning text and apply this decorator to the class. - """ - if PY2: - if '__str__' not in klass.__dict__: - raise ValueError("@python_2_unicode_compatible cannot be applied " - "to %s because it doesn't define __str__()." % - klass.__name__) - klass.__unicode__ = klass.__str__ - klass.__str__ = lambda self: self.__unicode__().encode('utf-8') - return klass - - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -if globals().get("__spec__") is not None: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer)