├── .gitignore ├── README.md ├── __main__.py ├── client.py ├── common.py ├── ntlm.py ├── ntlm_auth ├── U32.py ├── __init__.py ├── compute_hash.py ├── compute_keys.py ├── compute_response.py ├── constants.py ├── des.py ├── des_c.py ├── des_data.py ├── gss_channel_bindings.py ├── messages.py ├── ntlm.py ├── rc4.py ├── session_security.py └── target_info.py ├── ordereddict.py ├── relay.py ├── server.py └── six.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__ 3 | .idea 4 | .vscode 5 | / 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rpivot2 - reverse SOCKS4 proxy for penetration tests 2 | 3 | Fork of [klsecservices/rpivot](https://github.com/klsecservices/rpivot) by Artem Kondratenko (https://twitter.com/artkond) 4 | 5 | Added by me: 6 | 7 | - rpivot2 works on Python 2 and Python 3. 8 | - rpivot2 works with host names. Original works only with IPs. 9 | - A shit ton of refactornig. 10 | 11 | 12 | ## Usage 13 | 14 | 1. Run the server on a pentester's machine and wait for a client to connect to it. 15 | 16 | python server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127.0.0.1 --proxy-port 1080 17 | 18 | 2. Run the client on the machine you want to tunnel traffic through. 19 | 20 | python client.py --server-ip --server-port 9999 21 | 22 | ## Usage examples 23 | 24 | Start server listener on port 9999, which creates a socks 4 proxy on 127.0.0.1:1080 upon connection from client: 25 | 26 | `python server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127.0.0.1 --proxy-port 1080` 27 | 28 | Connect to the server: 29 | 30 | `python client.py --server-ip --server-port 9999` 31 | 32 | To pivot through an NTLM proxy: 33 | 34 | `python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd` 35 | 36 | Pass-the-hash is supported: 37 | 38 | `python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --hashes 9b9850751be2515c8231e5189015bbe6:49ef7638d69a01f26d96ed673bf50c45` 39 | 40 | You can use `proxychains` to tunnel traffic through socks proxy. 41 | 42 | Edit /etc/proxychains.conf: 43 | 44 | ``` 45 | [ProxyList] 46 | # add proxy here ... 47 | # meanwile 48 | # defaults set to "tor" 49 | socks4 127.0.0.1 1080 50 | ``` 51 | 52 | And you probably disable proxying DNS because SOCKS4 doesn't work with it. 53 | 54 | Using single zip file mode: 55 | 56 | ``` 57 | zip rpivot.zip -r *.py ./ntlm_auth/ 58 | python rpivot.zip server 59 | python rpivot.zip client 60 | ``` 61 | 62 | Pivot and have fun: 63 | 64 | `proxychains ` 65 | 66 | Pre-built Windows client binary available in release section. 67 | -------------------------------------------------------------------------------- /__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | try: 6 | rpivot_type = sys.argv.pop(1).lower() 7 | if rpivot_type not in ('client', 'server'): 8 | raise IndexError('Bad rpivot type') 9 | except IndexError: 10 | print('{} ...'.format(sys.argv[0])) 11 | sys.exit(1) 12 | 13 | if rpivot_type == 'client': 14 | import client 15 | 16 | client.main() 17 | elif rpivot_type == 'server': 18 | import server 19 | 20 | server.main() 21 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import socket 4 | import re 5 | import sys 6 | import time 7 | from struct import unpack 8 | import select 9 | import optparse 10 | import errno 11 | import relay 12 | import threading 13 | from ntlm import NtlmProxyContext 14 | from common import create_logger, ls, Relay, RelayMainError 15 | 16 | 17 | def key_by_value(my_dict, value): 18 | for k, v in my_dict.items(): 19 | if v == value: 20 | return k 21 | return None 22 | 23 | 24 | class SocksRelay(Relay): 25 | 26 | def __init__(self, command_socket): 27 | super(SocksRelay, self).__init__(command_socket) 28 | self.establishing_dict = {} 29 | self.forward_socket = None 30 | self.data = None 31 | 32 | self.ping_thread = threading.Thread(target=self.ping_worker, name='Ping') 33 | self.ping_thread.start() 34 | 35 | # 36 | # Common methods 37 | # 38 | 39 | def ping_worker(self): 40 | while True: 41 | time.sleep(self.ping_delay) 42 | current_time = time.time() 43 | 44 | if self.remote_side_is_down: 45 | log.debug('Remote side down. Exiting ping worker') 46 | return 47 | 48 | if current_time - self.last_ping > self.relay_timeout: 49 | log.error('No response from remote side for {0} seconds. ' 50 | 'Restarting relay...'.format(relay.relay_timeout)) 51 | self.command_socket.close() 52 | return 53 | 54 | def close_connection_with_server(self): 55 | self.command_socket.close() 56 | self.input_connections.remove(self.command_socket) 57 | 58 | # 59 | # Handle commands 60 | # 61 | 62 | def close_channel_hdl(self, channel_id): 63 | establishing_sock = key_by_value(self.establishing_dict, channel_id) 64 | if establishing_sock is not None: 65 | log.debug('[{0}] Closing establishing channel...'.format(channel_id)) 66 | del self.establishing_dict[establishing_sock] 67 | return 68 | 69 | elif channel_id not in self.channels: 70 | log.debug('Channel {0} non existent'.format(channel_id)) 71 | return 72 | 73 | sock_to_close = self.channels[channel_id] 74 | self.unset_channel(channel_id) 75 | log.debug('[{}] Closing channel...'.format(channel_id)) 76 | sock_to_close.close() 77 | self.input_connections.remove(sock_to_close) 78 | 79 | def open_channel_hdl(self, data): 80 | channel_id, packed_ip, port = unpack('BBHI', data[:8]) 126 | except struct.error: 127 | raise RelayMainError('Invalid socks header! Got data: {0}'.format(repr(data))) 128 | 129 | if vn != 4: 130 | raise RelayMainError('Invalid socks header! Only Socks4 supported') 131 | 132 | str_ip = socket.inet_ntoa(struct.pack(">L", dstip)) 133 | log.debug('Got header: socks version: {0}; socks command: {1}; dst: {2}:{3}'.format(vn, cd, str_ip, dstport)) 134 | return str_ip, dstport 135 | 136 | def get_channel_data(self): 137 | """ 138 | Getting data from the command socket (from client or from server). 139 | @return: tuple[int,bytes] 140 | @raise: RelayMainError 141 | """ 142 | try: 143 | tlv_header = self.__recvall(self.command_socket, 4) 144 | channel_id, tlv_data_len = struct.unpack(' 3 | # 4 | # This library is free software: you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation, either 7 | # version 3 of the License, or (at your option) any later version. 8 | 9 | # This library is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this library. If not, see or . 16 | 17 | from __future__ import division 18 | import six 19 | 20 | C = 0x1000000000 21 | 22 | 23 | def norm(n): 24 | return n & 0xFFFFFFFF 25 | 26 | 27 | class U32: 28 | v = 0 29 | 30 | def __init__(self, value=0): 31 | if not isinstance(value, six.integer_types): 32 | value = six.byte2int(value) 33 | 34 | self.v = C + norm(abs(int(value))) 35 | 36 | def set(self, value=0): 37 | self.v = C + norm(abs(int(value))) 38 | 39 | def __repr__(self): 40 | return hex(norm(self.v)) 41 | 42 | def __long__(self): 43 | return int(norm(self.v)) 44 | 45 | def __int__(self): 46 | return int(norm(self.v)) 47 | 48 | def __chr__(self): 49 | return chr(norm(self.v)) 50 | 51 | def __add__(self, b): 52 | r = U32() 53 | r.v = C + norm(self.v + b.v) 54 | return r 55 | 56 | def __sub__(self, b): 57 | r = U32() 58 | if self.v < b.v: 59 | r.v = C + norm(0x100000000 - (b.v - self.v)) 60 | else: 61 | r.v = C + norm(self.v - b.v) 62 | return r 63 | 64 | def __mul__(self, b): 65 | r = U32() 66 | r.v = C + norm(self.v * b.v) 67 | return r 68 | 69 | def __div__(self, b): 70 | r = U32() 71 | r.v = C + (norm(self.v) // norm(b.v)) 72 | return r 73 | 74 | def __truediv__(self, b): 75 | r = U32() 76 | r.v = C + (norm(self.v) / norm(b.v)) 77 | return r 78 | 79 | def __mod__(self, b): 80 | r = U32() 81 | r.v = C + (norm(self.v) % norm(b.v)) 82 | return r 83 | 84 | def __neg__(self): 85 | return U32(self.v) 86 | 87 | def __pos__(self): 88 | return U32(self.v) 89 | 90 | def __abs__(self): 91 | return U32(self.v) 92 | 93 | def __invert__(self): 94 | r = U32() 95 | r.v = C + norm(~self.v) 96 | return r 97 | 98 | def __lshift__(self, b): 99 | r = U32() 100 | r.v = C + norm(self.v << b) 101 | return r 102 | 103 | def __rshift__(self, b): 104 | r = U32() 105 | r.v = C + (norm(self.v) >> b) 106 | return r 107 | 108 | def __and__(self, b): 109 | r = U32() 110 | r.v = C + norm(self.v & b.v) 111 | return r 112 | 113 | def __or__(self, b): 114 | r = U32() 115 | r.v = C + norm(self.v | b.v) 116 | return r 117 | 118 | def __xor__(self, b): 119 | r = U32() 120 | r.v = C + norm(self.v ^ b.v) 121 | return r 122 | 123 | def __not__(self): 124 | return U32(not norm(self.v)) 125 | 126 | def truth(self): 127 | return norm(self.v) 128 | 129 | def __cmp__(self, b): 130 | if norm(self.v) > norm(b.v): 131 | return 1 132 | elif norm(self.v) < norm(b.v): 133 | return -1 134 | else: 135 | return 0 136 | 137 | def __lt__(self, other): 138 | return self.v < other.v 139 | 140 | def __gt__(self, other): 141 | return self.v > other.v 142 | 143 | def __eq__(self, other): 144 | return self.v == other.v 145 | 146 | def __le__(self, other): 147 | return self.v <= other.v 148 | 149 | def __ge__(self, other): 150 | return self.v >= other.v 151 | 152 | def __ne__(self, other): 153 | return self.v != other.v 154 | 155 | def __nonzero__(self): 156 | return norm(self.v) 157 | -------------------------------------------------------------------------------- /ntlm_auth/__init__.py: -------------------------------------------------------------------------------- 1 | from . import ntlm, session_security 2 | 3 | __all__ = ('ntlm', 'session_security') 4 | -------------------------------------------------------------------------------- /ntlm_auth/compute_hash.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | import hashlib 15 | import hmac 16 | from ntlm_auth import des 17 | 18 | 19 | def _lmowfv1(password, lmhash): 20 | """ 21 | [MS-NLMP] v28.0 2016-07-14 22 | 23 | 3.3.1 NTLM v1 Authentication 24 | Same function as LMOWFv1 in document to create a one way hash of the password. Only 25 | used in NTLMv1 auth without session security 26 | 27 | @param password: The password of the user we are trying to authenticate with 28 | @param lmhash: ... 29 | :return res: A Lan Manager hash of the password supplied 30 | """ 31 | 32 | # fix the password length to 14 bytes 33 | if lmhash is not None: 34 | return lmhash.decode('hex') 35 | 36 | password = password.upper() 37 | lm_pw = password[0:14] 38 | 39 | # do hash 40 | magic_str = b"KGS!@#$%" # page 56 in [MS-NLMP v28.0] 41 | 42 | res = b'' 43 | dobj = des.DES(lm_pw[0:7]) 44 | res = res + dobj.encrypt(magic_str) 45 | 46 | dobj = des.DES(lm_pw[7:14]) 47 | res = res + dobj.encrypt(magic_str) 48 | return res 49 | 50 | 51 | def _ntowfv1(password, nthash): 52 | """ 53 | [MS-NLMP] v28.0 2016-07-14 54 | 55 | 3.3.1 NTLM v1 Authentication 56 | Same function as NTOWFv1 in document to create a one way hash of the password. Only 57 | used in NTLMv1 auth without session security 58 | 59 | @param password: The password of the user we are trying to authenticate with 60 | @param nthash: ... 61 | :return digest: An NT hash of the password supplied 62 | """ 63 | if nthash is not None: 64 | return nthash.decode('hex') 65 | 66 | digest = hashlib.new('md4', password.encode('utf-16le')).digest() 67 | return digest 68 | 69 | 70 | def _ntowfv2(user_name, password, nthash, domain_name): 71 | """ 72 | [MS-NLMP] v28.0 2016-07-14 73 | 74 | 3.3.2 NTLM v2 Authentication 75 | Same function as NTOWFv2 (and LMOWFv2) in document to create a one way hash of the password. 76 | This combines some extra security features over the v1 calculations used in NTLMv2 auth. 77 | 78 | @param user_name: The username of the user we are trying to authenticate with 79 | @param password: The password of the user we are trying to authenticate with 80 | @param nthash: ... 81 | @param domain_name: The domain name of the user account we are authenticated with 82 | @return digest: An NT hash of the parameters supplied 83 | """ 84 | digest = _ntowfv1(password, nthash) 85 | digest = hmac.new(digest, (user_name.upper() + domain_name).encode('utf-16le')).digest() 86 | 87 | return digest 88 | -------------------------------------------------------------------------------- /ntlm_auth/compute_keys.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | import binascii 15 | import hashlib 16 | import hmac 17 | from ntlm_auth import des 18 | from ntlm_auth.constants import NegotiateFlags 19 | 20 | 21 | def _get_exchange_key_ntlm_v1(negotiate_flags, session_base_key, server_challenge, lm_challenge_response, lm_hash): 22 | """ 23 | [MS-NLMP] v28.0 2016-07-14 24 | 25 | 4.3.5.1 KXKEY 26 | Calculates the Key Exchange Key for NTLMv1 authentication. Used for signing and sealing messages 27 | 28 | @param negotiate_flags: 29 | @param session_base_key: A session key calculated from the user password challenge 30 | @param server_challenge: A random 8-byte response generated by the server in the CHALLENGE_MESSAGE 31 | @param lm_challenge_response: The LmChallengeResponse value computed in ComputeResponse 32 | @param lm_hash: The LMOWF computed in Compute Response 33 | @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages and compute 34 | the ExportedSessionKey 35 | """ 36 | if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 37 | key_exchange_key = hmac.new(session_base_key, server_challenge + lm_challenge_response[:8]).digest() 38 | elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY: 39 | des_handler = des.DES(lm_hash[:7]) 40 | first_des = des_handler.encrypt(lm_challenge_response[:8]) 41 | des_handler = des.DES(lm_hash[7:8] + binascii.unhexlify('bdbdbdbdbdbdbd')) 42 | second_des = des_handler.encrypt(lm_challenge_response[:8]) 43 | 44 | key_exchange_key = first_des + second_des 45 | elif negotiate_flags & NegotiateFlags.NTLMSSP_REQUEST_NON_NT_SESSION_KEY: 46 | key_exchange_key = lm_hash[:8] + b'\0' * 8 47 | else: 48 | key_exchange_key = session_base_key 49 | 50 | return key_exchange_key 51 | 52 | 53 | def _get_exchange_key_ntlm_v2(session_base_key): 54 | """ 55 | [MS-NLMP] v28.0 2016-07-14 56 | 57 | 4.3.5.1 KXKEY 58 | Calculates the Key Exchange Key for NTLMv2 authentication. Used for signing and sealing messages. 59 | According to docs, 'If NTLM v2 is used, KeyExchangeKey MUST be set to the given 128-bit SessionBaseKey 60 | 61 | @param session_base_key: A session key calculated from the user password challenge 62 | @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages 63 | """ 64 | return session_base_key 65 | 66 | 67 | def get_sign_key(exported_session_key, magic_constant): 68 | """ 69 | 3.4.5.2 SIGNKEY 70 | 71 | @param exported_session_key: A 128-bit session key used to derive signing and sealing keys 72 | @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) 73 | @return sign_key: Key used to sign messages 74 | """ 75 | 76 | sign_key = hashlib.md5(exported_session_key + magic_constant).digest() 77 | 78 | return sign_key 79 | 80 | 81 | def get_seal_key(negotiate_flags, exported_session_key, magic_constant): 82 | """ 83 | 3.4.5.3. SEALKEY 84 | Main method to use to calculate the seal_key used to seal (encrypt) messages. This will determine 85 | the correct method below to use based on the compatibility flags set and should be called instead 86 | of the others 87 | 88 | @param exported_session_key: A 128-bit session key used to derive signing and sealing keys 89 | @param negotiate_flags: The negotiate_flags structure sent by the server 90 | @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) 91 | @return seal_key: Key used to seal messages 92 | """ 93 | 94 | if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 95 | seal_key = _get_seal_key_ntlm2(negotiate_flags, exported_session_key, magic_constant) 96 | elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY: 97 | seal_key = _get_seal_key_ntlm1(negotiate_flags, exported_session_key) 98 | else: 99 | seal_key = exported_session_key 100 | 101 | return seal_key 102 | 103 | 104 | def _get_seal_key_ntlm1(negotiate_flags, exported_session_key): 105 | """ 106 | 3.4.5.3 SEALKEY 107 | Calculates the seal_key used to seal (encrypt) messages. This for authentication where 108 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has not been negotiated. Will weaken the keys 109 | if NTLMSSP_NEGOTIATE_56 is not negotiated it will default to the 40-bit key 110 | 111 | @param negotiate_flags: The negotiate_flags structure sent by the server 112 | @param exported_session_key: A 128-bit session key used to derive signing and sealing keys 113 | @return seal_key: Key used to seal messages 114 | """ 115 | if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_56: 116 | seal_key = exported_session_key[:7] + binascii.unhexlify('a0') 117 | else: 118 | seal_key = exported_session_key[:5] + binascii.unhexlify('e538b0') 119 | 120 | return seal_key 121 | 122 | 123 | def _get_seal_key_ntlm2(negotiate_flags, exported_session_key, magic_constant): 124 | """ 125 | 3.4.5.3 SEALKEY 126 | Calculates the seal_key used to seal (encrypt) messages. This for authentication where 127 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has been negotiated. Will weaken the keys 128 | if NTLMSSP_NEGOTIATE_128 is not negotiated, will try NEGOTIATE_56 and then will default 129 | to the 40-bit key 130 | 131 | @param negotiate_flags: The negotiate_flags structure sent by the server 132 | @param exported_session_key: A 128-bit session key used to derive signing and sealing keys 133 | @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) 134 | @return seal_key: Key used to seal messages 135 | """ 136 | if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_128: 137 | seal_key = exported_session_key 138 | elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_56: 139 | seal_key = exported_session_key[:7] 140 | else: 141 | seal_key = exported_session_key[:5] 142 | 143 | seal_key = hashlib.md5(seal_key + magic_constant).digest() 144 | 145 | return seal_key 146 | -------------------------------------------------------------------------------- /ntlm_auth/compute_response.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | import base64 15 | import calendar 16 | import hashlib 17 | import hmac 18 | import os 19 | import struct 20 | import time 21 | import ntlm_auth.compute_hash as comphash 22 | import ntlm_auth.compute_keys as compkeys 23 | from ntlm_auth import des 24 | from ntlm_auth.constants import NegotiateFlags, AvFlags 25 | from ntlm_auth.gss_channel_bindings import GssChannelBindingsStruct 26 | from ntlm_auth.target_info import TargetInfo 27 | 28 | 29 | class ComputeResponse(object): 30 | """ 31 | Constructor for the response computations. This class will compute the various nt and lm challenge responses. 32 | 33 | @param user_name: The username of the user we are trying to authenticate with 34 | @param password: The password of the user we are trying to authenticate with 35 | @param domain_name: The domain name of the user account we are authenticated with, default is None 36 | @param challenge_message: A ChallengeMessage object that was received from the server after the negotiate_message 37 | @param ntlm_compatibility: The Lan Manager Compatibility Level, used to determine what NTLM auth version to use, 38 | see Ntlm in ntlm.py for more details 39 | """ 40 | 41 | def __init__(self, user_name, password, nthash, lmhash, domain_name, challenge_message, ntlm_compatibility): 42 | self._user_name = user_name 43 | self._password = password 44 | self._nthash = nthash 45 | self._lmhash = lmhash 46 | self._domain_name = domain_name 47 | self._challenge_message = challenge_message 48 | self._negotiate_flags = challenge_message.negotiate_flags 49 | self._server_challenge = challenge_message.server_challenge 50 | self._server_target_info = challenge_message.target_info 51 | self._ntlm_compatibility = ntlm_compatibility 52 | self._client_challenge = os.urandom(8) 53 | 54 | def get_lm_challenge_response(self): 55 | """ 56 | [MS-NLMP] v28.0 2016-07-14 57 | 58 | 3.3.1 - NTLM v1 Authentication 59 | 3.3.2 - NTLM v2 Authentication 60 | 61 | This method returns the LmChallengeResponse key based on the ntlm_compatibility chosen 62 | and the target_info supplied by the CHALLENGE_MESSAGE. It is quite different from what 63 | is set in the document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one 64 | and calls separate methods based on the ntlm_compatibility flag chosen. 65 | 66 | @return: response (LmChallengeResponse) - The LM response to the server challenge. Computed by the client 67 | """ 68 | if self._negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY \ 69 | and self._ntlm_compatibility < 3: 70 | response = ComputeResponse._get_LMv1_with_session_security_response(self._client_challenge) 71 | 72 | elif 0 <= self._ntlm_compatibility <= 1: 73 | response = ComputeResponse._get_LMv1_response(self._password, self._lmhash, self._server_challenge) 74 | elif self._ntlm_compatibility == 2: 75 | # Based on the compatibility level we don't want to use LM responses, 76 | # ignore the session_base_key as it is returned in nt 77 | response, ignore_key = ComputeResponse._get_NTLMv1_response(self._password, self._nthash, 78 | self._server_challenge) 79 | else: 80 | """ 81 | [MS-NLMP] v28.0 page 45 - 2016-07-14 82 | 83 | 3.1.5.12 Client Received a CHALLENGE_MESSAGE from the Server 84 | If NTLMv2 authentication is used and the CHALLENGE_MESSAGE TargetInfo field has an MsvAvTimestamp present, 85 | the client SHOULD NOT send the LmChallengeResponse and SHOULD send Z(24) instead. 86 | """ 87 | 88 | response = ComputeResponse._get_LMv2_response(self._user_name, self._password, self._nthash, 89 | self._domain_name, 90 | self._server_challenge, 91 | self._client_challenge) 92 | if self._server_target_info is not None: 93 | timestamp = self._server_target_info[TargetInfo.MSV_AV_TIMESTAMP] 94 | if timestamp is not None: 95 | response = b'\0' * 24 96 | 97 | return response 98 | 99 | def get_nt_challenge_response(self, lm_challenge_response, server_certificate_hash): 100 | """ 101 | [MS-NLMP] v28.0 2016-07-14 102 | 103 | 3.3.1 - NTLM v1 Authentication 104 | 3.3.2 - NTLM v2 Authentication 105 | 106 | This method returns the NtChallengeResponse key based on the ntlm_compatibility chosen 107 | and the target_info supplied by the CHALLENGE_MESSAGE. It is quite different from what 108 | is set in the document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one 109 | and calls separate methods based on the ntlm_compatibility value chosen. 110 | 111 | @param lm_challenge_response: The LmChallengeResponse calculated beforeand, used to get the key_exchange_key value 112 | @param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to. 113 | Used in Channel Binding Tokens if present, default value is None. See 114 | AuthenticateMessage in messages.py for more details 115 | @return response: (NtChallengeResponse) - The NT response to the server challenge. Computed by the client 116 | @return session_base_key: (SessionBaseKey) - A session key calculated from the user password challenge 117 | @return target_info: (AV_PAIR) - The AV_PAIR structure used in the nt_challenge calculations 118 | """ 119 | if self._negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY \ 120 | and self._ntlm_compatibility < 3: 121 | # The compatibility level is less than 3 which means it doesn't support NTLMv2 122 | # but we want extended security so use NTLM2 which is different from NTLMv2 123 | # [MS-NLMP] - 3.3.1 NTLMv1 Authentication 124 | response, session_base_key = ComputeResponse._get_NTLM2_response(self._password, self._nthash, 125 | self._server_challenge, 126 | self._client_challenge) 127 | key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key, 128 | self._server_challenge, lm_challenge_response, 129 | comphash._lmowfv1(self._password, self._lmhash)) 130 | target_info = None 131 | 132 | elif 0 <= self._ntlm_compatibility < 3: 133 | response, session_base_key = ComputeResponse._get_NTLMv1_response(self._password, self._nthash, 134 | self._server_challenge) 135 | key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key, 136 | self._server_challenge, lm_challenge_response, 137 | comphash._lmowfv1(self._password, self._lmhash)) 138 | target_info = None 139 | else: 140 | if self._server_target_info is None: 141 | target_info = TargetInfo() 142 | else: 143 | target_info = self._server_target_info 144 | 145 | if target_info[TargetInfo.MSV_AV_TIMESTAMP] is None: 146 | timestamp = get_windows_timestamp() 147 | else: 148 | timestamp = target_info[TargetInfo.MSV_AV_TIMESTAMP][1] 149 | 150 | # [MS-NLMP] If the CHALLENGE_MESSAGE TargetInfo field has an MsvAvTimestamp present, 151 | # the client SHOULD provide a MIC 152 | target_info[TargetInfo.MSV_AV_FLAGS] = struct.pack(" or . 13 | 14 | """ 15 | [MS-NLMP] v28.0 2016-07-14 16 | 17 | 2.2 Message Syntax 18 | The signature field used in NTLM messages 19 | """ 20 | NTLM_SIGNATURE = b'NTLMSSP\0' 21 | 22 | """ 23 | [MS-NLMP] v28.0 2016-07-14 24 | 25 | 2.2 Message Syntax 26 | The 3 message type options you can have in a message. 27 | """ 28 | 29 | 30 | class MessageTypes(object): 31 | NTLM_NEGOTIATE = 0x1 32 | NTLM_CHALLENGE = 0x2 33 | NTLM_AUTHENTICATE = 0x3 34 | 35 | 36 | """ 37 | [MS-NLMP] v28.0 2016-07-14 38 | 39 | 2.2.2.1 AV_PAIR (MsvAvFlags) 40 | A 32-bit value indicated server or client configuration 41 | """ 42 | 43 | 44 | class AvFlags(object): 45 | AUTHENTICATION_CONSTRAINED = 0x1 46 | MIC_PROVIDED = 0x2 47 | UNTRUSTED_SPN_SOURCE = 0x4 48 | 49 | 50 | """ 51 | [MS-NLMP] v28.0 2016-07-14 52 | 53 | 2.2.2.5 NEGOTIATE 54 | During NTLM authentication, each of the following flags is a possible value of the 55 | NegotiateFlags field of the NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE and AUTHENTICATE_MESSAGE, 56 | unless otherwise noted. These flags define client or server NTLM capabilities 57 | supported by the sender. 58 | """ 59 | 60 | 61 | class NegotiateFlags(object): 62 | NTLMSSP_NEGOTIATE_56 = 0x80000000 63 | NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000 64 | NTLMSSP_NEGOTIATE_128 = 0x20000000 65 | NTLMSSP_RESERVED_R1 = 0x10000000 66 | NTLMSSP_RESERVED_R2 = 0x08000000 67 | NTLMSSP_RESERVED_R3 = 0x04000000 68 | NTLMSSP_NEGOTIATE_VERSION = 0x02000000 69 | NTLMSSP_RESERVED_R4 = 0x01000000 70 | NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000 71 | NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000 72 | NTLMSSP_RESERVED_R5 = 0x00200000 73 | NTLMSSP_NEGOTIATE_IDENTITY = 0x00100000 74 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000 75 | NTLMSSP_RESERVED_R6 = 0x00040000 76 | NTLMSSP_TARGET_TYPE_SERVER = 0x00020000 77 | NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000 78 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 79 | NTLMSSP_RESERVED_R7 = 0x00004000 80 | NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000 81 | NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000 82 | NTLMSSP_ANOYNMOUS = 0x00000800 83 | NTLMSSP_RESERVED_R8 = 0x00000400 84 | NTLMSSP_NEGOTIATE_NTLM = 0x00000200 85 | NTLMSSP_RESERVED_R9 = 0x00000100 86 | NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080 87 | NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040 88 | NTLMSSP_NEGOTIATE_SEAL = 0x00000020 89 | NTLMSSP_NEGOTIATE_SIGN = 0x00000010 90 | NTLMSSP_RESERVED_R10 = 0x00000008 91 | NTLMSSP_REQUEST_TARGET = 0x00000004 92 | NTLMSSP_NEGOTIATE_OEM = 0x00000002 93 | NTLMSSP_NEGOTIATE_UNICODE = 0x00000001 94 | 95 | 96 | class SignSealConstants(object): 97 | # Magic Contants used to get the signing and sealing key for Extended Session Security 98 | CLIENT_SIGNING = b"session key to client-to-server signing key magic constant\0" 99 | SERVER_SIGNING = b"session key to server-to-client signing key magic constant\0" 100 | CLIENT_SEALING = b"session key to client-to-server sealing key magic constant\0" 101 | SERVER_SEALING = b"session key to server-to-client sealing key magic constant\0" 102 | -------------------------------------------------------------------------------- /ntlm_auth/des.py: -------------------------------------------------------------------------------- 1 | # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ 2 | # Copyright 2001 Dmitry A. Rozmanov 3 | # 4 | # This library is free software: you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation, either 7 | # version 3 of the License, or (at your option) any later version. 8 | 9 | # This library is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this library. If not, see or . 16 | import logging 17 | import six 18 | from ntlm_auth import des_c 19 | 20 | log = logging.getLogger(__name__) 21 | 22 | 23 | class DES: 24 | des_c_obj = None 25 | 26 | def __init__(self, key_str): 27 | k = str_to_key56(key_str) 28 | k = key56_to_key64(k) 29 | 30 | key_str = b'' 31 | for i in k: 32 | key_str += six.int2byte(i & 0xFF) 33 | 34 | self.des_c_obj = des_c.DES(key_str) 35 | 36 | def encrypt(self, plain_text): 37 | return self.des_c_obj.encrypt(plain_text) 38 | 39 | def decrypt(self, crypted_text): 40 | return self.des_c_obj.decrypt(crypted_text) 41 | 42 | 43 | DESException = 'DESException' 44 | 45 | 46 | def str_to_key56(key_str): 47 | if not type(key_str) == six.binary_type: 48 | # TODO rsanders high - figure out how to make this not necessary 49 | key_str = key_str.encode('ascii') 50 | 51 | if len(key_str) < 7: 52 | key_str = key_str + b'\000\000\000\000\000\000\000'[:(7 - len(key_str))] 53 | key_56 = [] 54 | for i in six.iterbytes(key_str[:7]): 55 | key_56.append(i) 56 | 57 | return key_56 58 | 59 | 60 | def key56_to_key64(key_56): 61 | key = [] 62 | for i in range(8): 63 | key.append(0) 64 | 65 | key[0] = key_56[0] 66 | key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1) 67 | key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2) 68 | key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3) 69 | key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4) 70 | key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5) 71 | key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6) 72 | key[7] = (key_56[6] << 1) & 0xFF 73 | 74 | key = set_key_odd_parity(key) 75 | 76 | return key 77 | 78 | 79 | def set_key_odd_parity(key): 80 | for i in range(len(key)): 81 | for k in range(7): 82 | bit = 0 83 | t = key[i] >> k 84 | bit = (t ^ bit) & 0x1 85 | key[i] = (key[i] & 0xFE) | bit 86 | 87 | return key 88 | -------------------------------------------------------------------------------- /ntlm_auth/des_c.py: -------------------------------------------------------------------------------- 1 | # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ 2 | # Copyright 2001 Dmitry A. Rozmanov 3 | # 4 | # This library is free software: you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation, either 7 | # version 3 of the License, or (at your option) any later version. 8 | 9 | # This library is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this library. If not, see or . 16 | import six 17 | 18 | from ntlm_auth.U32 import U32 19 | from ntlm_auth.des_data import des_SPtrans, des_skb 20 | 21 | 22 | def c2l(c): 23 | """char[4] to unsigned long""" 24 | l = U32(c[0]) 25 | l = l | (U32(c[1]) << 8) 26 | l = l | (U32(c[2]) << 16) 27 | l = l | (U32(c[3]) << 24) 28 | return l 29 | 30 | 31 | def l2c(l): 32 | """unsigned long to char[4]""" 33 | c = [] 34 | c.append(int(l & U32(0xFF))) 35 | c.append(int((l >> 8) & U32(0xFF))) 36 | c.append(int((l >> 16) & U32(0xFF))) 37 | c.append(int((l >> 24) & U32(0xFF))) 38 | return c 39 | 40 | 41 | def D_ENCRYPT(tup, u, t, s): 42 | L, R, S = tup 43 | # print 'LRS1', L, R, S, u, t, '-->', 44 | u = (R ^ s[S]) 45 | t = R ^ s[S + 1] 46 | t = ((t >> 4) + (t << 28)) 47 | L = L ^ (des_SPtrans[1][int((t) & U32(0x3f))] | 48 | des_SPtrans[3][int((t >> 8) & U32(0x3f))] | 49 | des_SPtrans[5][int((t >> 16) & U32(0x3f))] | 50 | des_SPtrans[7][int((t >> 24) & U32(0x3f))] | 51 | des_SPtrans[0][int((u) & U32(0x3f))] | 52 | des_SPtrans[2][int((u >> 8) & U32(0x3f))] | 53 | des_SPtrans[4][int((u >> 16) & U32(0x3f))] | 54 | des_SPtrans[6][int((u >> 24) & U32(0x3f))]) 55 | # print 'LRS:', L, R, S, u, t 56 | return (L, R, S), u, t, s 57 | 58 | 59 | def PERM_OP(tup, n, m): 60 | """tup - (a, b, t)""" 61 | a, b, t = tup 62 | t = ((a >> n) ^ b) & m 63 | b = b ^ t 64 | a = a ^ (t << n) 65 | return (a, b, t) 66 | 67 | 68 | def HPERM_OP(tup, n, m): 69 | "tup - (a, t)" 70 | a, t = tup 71 | t = ((a << (16 - n)) ^ a) & m 72 | a = a ^ t ^ (t >> (16 - n)) 73 | return a, t 74 | 75 | 76 | shifts2 = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0] 77 | 78 | 79 | class DES: 80 | KeySched = None # des_key_schedule 81 | 82 | def __init__(self, key_str): 83 | self.KeySched = des_set_key(key_str) 84 | 85 | def decrypt(self, str): 86 | # block - UChar[] 87 | block = [] 88 | 89 | for i in six.iterbytes(str): 90 | block.append(i) 91 | 92 | # print block 93 | block = des_ecb_encrypt(block, self.KeySched, 0) 94 | 95 | res = b'' 96 | for i in block: 97 | res = res + six.int2byte(i) 98 | 99 | return res 100 | 101 | def encrypt(self, plaintext): 102 | # block - UChar[] 103 | 104 | block = [] 105 | for i in plaintext: 106 | block.append(i) 107 | 108 | block = des_ecb_encrypt(block, self.KeySched, 1) 109 | 110 | res = b'' 111 | 112 | for i in block: 113 | res += six.int2byte(i) 114 | 115 | return res 116 | 117 | 118 | def des_encript(input, ks, encrypt): 119 | # input - U32[] 120 | # output - U32[] 121 | # ks - des_key_shedule - U32[2][16] 122 | # encrypt - int 123 | # l, r, t, u - U32 124 | # i - int 125 | # s - U32[] 126 | 127 | l = input[0] 128 | r = input[1] 129 | t = U32(0) 130 | u = U32(0) 131 | 132 | r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0f)) 133 | l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffff)) 134 | r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333)) 135 | l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ff)) 136 | r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555)) 137 | 138 | t = (r << 1) | (r >> 31) 139 | r = (l << 1) | (l >> 31) 140 | l = t 141 | 142 | s = ks # ??????????????? 143 | # print l, r 144 | if encrypt: 145 | for i in range(0, 32, 4): 146 | rtup, u, t, s = D_ENCRYPT((l, r, i + 0), u, t, s) 147 | l = rtup[0] 148 | r = rtup[1] 149 | rtup, u, t, s = D_ENCRYPT((r, l, i + 2), u, t, s) 150 | r = rtup[0] 151 | l = rtup[1] 152 | else: 153 | for i in range(30, 0, -4): 154 | rtup, u, t, s = D_ENCRYPT((l, r, i - 0), u, t, s) 155 | l = rtup[0] 156 | r = rtup[1] 157 | rtup, u, t, s = D_ENCRYPT((r, l, i - 2), u, t, s) 158 | r = rtup[0] 159 | l = rtup[1] 160 | # print l, r 161 | l = (l >> 1) | (l << 31) 162 | r = (r >> 1) | (r << 31) 163 | 164 | r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555)) 165 | l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ff)) 166 | r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333)) 167 | l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffff)) 168 | r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0f)) 169 | 170 | output = [l] 171 | output.append(r) 172 | l, r, t, u = U32(0), U32(0), U32(0), U32(0) 173 | return output 174 | 175 | 176 | def des_ecb_encrypt(input, ks, encrypt): 177 | # input - des_cblock - UChar[8] 178 | # output - des_cblock - UChar[8] 179 | # ks - des_key_shedule - U32[2][16] 180 | # encrypt - int 181 | 182 | # print input 183 | l0 = c2l(input[0:4]) 184 | l1 = c2l(input[4:8]) 185 | ll = [l0] 186 | ll.append(l1) 187 | # print ll 188 | ll = des_encript(ll, ks, encrypt) 189 | # print ll 190 | l0 = ll[0] 191 | l1 = ll[1] 192 | output = l2c(l0) 193 | output = output + l2c(l1) 194 | # print output 195 | l0, l1, ll[0], ll[1] = U32(0), U32(0), U32(0), U32(0) 196 | return output 197 | 198 | 199 | def des_set_key(key): 200 | # key - des_cblock - UChar[8] 201 | # schedule - des_key_schedule 202 | 203 | # register unsigned long c,d,t,s; 204 | # register unsigned char *in; 205 | # register unsigned long *k; 206 | # register int i; 207 | 208 | # k = schedule 209 | # in = key 210 | 211 | k = [] 212 | c = c2l(key[0:4]) 213 | d = c2l(key[4:8]) 214 | t = U32(0) 215 | 216 | d, c, t = PERM_OP((d, c, t), 4, U32(0x0f0f0f0f)) 217 | c, t = HPERM_OP((c, t), -2, U32(0xcccc0000)) 218 | d, t = HPERM_OP((d, t), -2, U32(0xcccc0000)) 219 | d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555)) 220 | c, d, t = PERM_OP((c, d, t), 8, U32(0x00ff00ff)) 221 | d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555)) 222 | 223 | d = (((d & U32(0x000000ff)) << 16) | (d & U32(0x0000ff00)) | ((d & U32(0x00ff0000)) >> 16) | ( 224 | (c & U32(0xf0000000)) >> 4)) 225 | c = c & U32(0x0fffffff) 226 | 227 | for i in range(16): 228 | if (shifts2[i]): 229 | c = ((c >> 2) | (c << 26)) 230 | d = ((d >> 2) | (d << 26)) 231 | else: 232 | c = ((c >> 1) | (c << 27)) 233 | d = ((d >> 1) | (d << 27)) 234 | c = c & U32(0x0fffffff) 235 | d = d & U32(0x0fffffff) 236 | 237 | s = des_skb[0][int((c) & U32(0x3f))] | \ 238 | des_skb[1][int(((c >> 6) & U32(0x03)) | ((c >> 7) & U32(0x3c)))] | \ 239 | des_skb[2][int(((c >> 13) & U32(0x0f)) | ((c >> 14) & U32(0x30)))] | \ 240 | des_skb[3][int(((c >> 20) & U32(0x01)) | ((c >> 21) & U32(0x06)) | ((c >> 22) & U32(0x38)))] 241 | 242 | t = des_skb[4][int((d) & U32(0x3f))] | \ 243 | des_skb[5][int(((d >> 7) & U32(0x03)) | ((d >> 8) & U32(0x3c)))] | \ 244 | des_skb[6][int((d >> 15) & U32(0x3f))] | \ 245 | des_skb[7][int(((d >> 21) & U32(0x0f)) | ((d >> 22) & U32(0x30)))] 246 | # print s, t 247 | 248 | k.append(((t << 16) | (s & U32(0x0000ffff))) & U32(0xffffffff)) 249 | s = ((s >> 16) | (t & U32(0xffff0000))) 250 | s = (s << 4) | (s >> 28) 251 | k.append(s & U32(0xffffffff)) 252 | 253 | schedule = k 254 | 255 | return schedule 256 | -------------------------------------------------------------------------------- /ntlm_auth/des_data.py: -------------------------------------------------------------------------------- 1 | # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ 2 | # Copyright 2001 Dmitry A. Rozmanov 3 | # 4 | # This library is free software: you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation, either 7 | # version 3 of the License, or (at your option) any later version. 8 | 9 | # This library is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this library. If not, see or . 16 | 17 | from ntlm_auth.U32 import U32 18 | 19 | # static unsigned long des_SPtrans[8][64]={ 20 | 21 | des_SPtrans = \ 22 | [ 23 | # nibble 0 24 | [ 25 | U32(0x00820200), U32(0x00020000), U32(0x80800000), U32(0x80820200), 26 | U32(0x00800000), U32(0x80020200), U32(0x80020000), U32(0x80800000), 27 | U32(0x80020200), U32(0x00820200), U32(0x00820000), U32(0x80000200), 28 | U32(0x80800200), U32(0x00800000), U32(0x00000000), U32(0x80020000), 29 | U32(0x00020000), U32(0x80000000), U32(0x00800200), U32(0x00020200), 30 | U32(0x80820200), U32(0x00820000), U32(0x80000200), U32(0x00800200), 31 | U32(0x80000000), U32(0x00000200), U32(0x00020200), U32(0x80820000), 32 | U32(0x00000200), U32(0x80800200), U32(0x80820000), U32(0x00000000), 33 | U32(0x00000000), U32(0x80820200), U32(0x00800200), U32(0x80020000), 34 | U32(0x00820200), U32(0x00020000), U32(0x80000200), U32(0x00800200), 35 | U32(0x80820000), U32(0x00000200), U32(0x00020200), U32(0x80800000), 36 | U32(0x80020200), U32(0x80000000), U32(0x80800000), U32(0x00820000), 37 | U32(0x80820200), U32(0x00020200), U32(0x00820000), U32(0x80800200), 38 | U32(0x00800000), U32(0x80000200), U32(0x80020000), U32(0x00000000), 39 | U32(0x00020000), U32(0x00800000), U32(0x80800200), U32(0x00820200), 40 | U32(0x80000000), U32(0x80820000), U32(0x00000200), U32(0x80020200), 41 | ], 42 | 43 | # nibble 1 44 | [ 45 | U32(0x10042004), U32(0x00000000), U32(0x00042000), U32(0x10040000), 46 | U32(0x10000004), U32(0x00002004), U32(0x10002000), U32(0x00042000), 47 | U32(0x00002000), U32(0x10040004), U32(0x00000004), U32(0x10002000), 48 | U32(0x00040004), U32(0x10042000), U32(0x10040000), U32(0x00000004), 49 | U32(0x00040000), U32(0x10002004), U32(0x10040004), U32(0x00002000), 50 | U32(0x00042004), U32(0x10000000), U32(0x00000000), U32(0x00040004), 51 | U32(0x10002004), U32(0x00042004), U32(0x10042000), U32(0x10000004), 52 | U32(0x10000000), U32(0x00040000), U32(0x00002004), U32(0x10042004), 53 | U32(0x00040004), U32(0x10042000), U32(0x10002000), U32(0x00042004), 54 | U32(0x10042004), U32(0x00040004), U32(0x10000004), U32(0x00000000), 55 | U32(0x10000000), U32(0x00002004), U32(0x00040000), U32(0x10040004), 56 | U32(0x00002000), U32(0x10000000), U32(0x00042004), U32(0x10002004), 57 | U32(0x10042000), U32(0x00002000), U32(0x00000000), U32(0x10000004), 58 | U32(0x00000004), U32(0x10042004), U32(0x00042000), U32(0x10040000), 59 | U32(0x10040004), U32(0x00040000), U32(0x00002004), U32(0x10002000), 60 | U32(0x10002004), U32(0x00000004), U32(0x10040000), U32(0x00042000), 61 | ], 62 | 63 | # nibble 2 64 | [ 65 | U32(0x41000000), U32(0x01010040), U32(0x00000040), U32(0x41000040), 66 | U32(0x40010000), U32(0x01000000), U32(0x41000040), U32(0x00010040), 67 | U32(0x01000040), U32(0x00010000), U32(0x01010000), U32(0x40000000), 68 | U32(0x41010040), U32(0x40000040), U32(0x40000000), U32(0x41010000), 69 | U32(0x00000000), U32(0x40010000), U32(0x01010040), U32(0x00000040), 70 | U32(0x40000040), U32(0x41010040), U32(0x00010000), U32(0x41000000), 71 | U32(0x41010000), U32(0x01000040), U32(0x40010040), U32(0x01010000), 72 | U32(0x00010040), U32(0x00000000), U32(0x01000000), U32(0x40010040), 73 | U32(0x01010040), U32(0x00000040), U32(0x40000000), U32(0x00010000), 74 | U32(0x40000040), U32(0x40010000), U32(0x01010000), U32(0x41000040), 75 | U32(0x00000000), U32(0x01010040), U32(0x00010040), U32(0x41010000), 76 | U32(0x40010000), U32(0x01000000), U32(0x41010040), U32(0x40000000), 77 | U32(0x40010040), U32(0x41000000), U32(0x01000000), U32(0x41010040), 78 | U32(0x00010000), U32(0x01000040), U32(0x41000040), U32(0x00010040), 79 | U32(0x01000040), U32(0x00000000), U32(0x41010000), U32(0x40000040), 80 | U32(0x41000000), U32(0x40010040), U32(0x00000040), U32(0x01010000), 81 | ], 82 | 83 | # nibble 3 84 | [ 85 | U32(0x00100402), U32(0x04000400), U32(0x00000002), U32(0x04100402), 86 | U32(0x00000000), U32(0x04100000), U32(0x04000402), U32(0x00100002), 87 | U32(0x04100400), U32(0x04000002), U32(0x04000000), U32(0x00000402), 88 | U32(0x04000002), U32(0x00100402), U32(0x00100000), U32(0x04000000), 89 | U32(0x04100002), U32(0x00100400), U32(0x00000400), U32(0x00000002), 90 | U32(0x00100400), U32(0x04000402), U32(0x04100000), U32(0x00000400), 91 | U32(0x00000402), U32(0x00000000), U32(0x00100002), U32(0x04100400), 92 | U32(0x04000400), U32(0x04100002), U32(0x04100402), U32(0x00100000), 93 | U32(0x04100002), U32(0x00000402), U32(0x00100000), U32(0x04000002), 94 | U32(0x00100400), U32(0x04000400), U32(0x00000002), U32(0x04100000), 95 | U32(0x04000402), U32(0x00000000), U32(0x00000400), U32(0x00100002), 96 | U32(0x00000000), U32(0x04100002), U32(0x04100400), U32(0x00000400), 97 | U32(0x04000000), U32(0x04100402), U32(0x00100402), U32(0x00100000), 98 | U32(0x04100402), U32(0x00000002), U32(0x04000400), U32(0x00100402), 99 | U32(0x00100002), U32(0x00100400), U32(0x04100000), U32(0x04000402), 100 | U32(0x00000402), U32(0x04000000), U32(0x04000002), U32(0x04100400), 101 | ], 102 | 103 | # nibble 4 104 | [ 105 | U32(0x02000000), U32(0x00004000), U32(0x00000100), U32(0x02004108), 106 | U32(0x02004008), U32(0x02000100), U32(0x00004108), U32(0x02004000), 107 | U32(0x00004000), U32(0x00000008), U32(0x02000008), U32(0x00004100), 108 | U32(0x02000108), U32(0x02004008), U32(0x02004100), U32(0x00000000), 109 | U32(0x00004100), U32(0x02000000), U32(0x00004008), U32(0x00000108), 110 | U32(0x02000100), U32(0x00004108), U32(0x00000000), U32(0x02000008), 111 | U32(0x00000008), U32(0x02000108), U32(0x02004108), U32(0x00004008), 112 | U32(0x02004000), U32(0x00000100), U32(0x00000108), U32(0x02004100), 113 | U32(0x02004100), U32(0x02000108), U32(0x00004008), U32(0x02004000), 114 | U32(0x00004000), U32(0x00000008), U32(0x02000008), U32(0x02000100), 115 | U32(0x02000000), U32(0x00004100), U32(0x02004108), U32(0x00000000), 116 | U32(0x00004108), U32(0x02000000), U32(0x00000100), U32(0x00004008), 117 | U32(0x02000108), U32(0x00000100), U32(0x00000000), U32(0x02004108), 118 | U32(0x02004008), U32(0x02004100), U32(0x00000108), U32(0x00004000), 119 | U32(0x00004100), U32(0x02004008), U32(0x02000100), U32(0x00000108), 120 | U32(0x00000008), U32(0x00004108), U32(0x02004000), U32(0x02000008), 121 | ], 122 | 123 | # nibble 5 124 | [ 125 | U32(0x20000010), U32(0x00080010), U32(0x00000000), U32(0x20080800), 126 | U32(0x00080010), U32(0x00000800), U32(0x20000810), U32(0x00080000), 127 | U32(0x00000810), U32(0x20080810), U32(0x00080800), U32(0x20000000), 128 | U32(0x20000800), U32(0x20000010), U32(0x20080000), U32(0x00080810), 129 | U32(0x00080000), U32(0x20000810), U32(0x20080010), U32(0x00000000), 130 | U32(0x00000800), U32(0x00000010), U32(0x20080800), U32(0x20080010), 131 | U32(0x20080810), U32(0x20080000), U32(0x20000000), U32(0x00000810), 132 | U32(0x00000010), U32(0x00080800), U32(0x00080810), U32(0x20000800), 133 | U32(0x00000810), U32(0x20000000), U32(0x20000800), U32(0x00080810), 134 | U32(0x20080800), U32(0x00080010), U32(0x00000000), U32(0x20000800), 135 | U32(0x20000000), U32(0x00000800), U32(0x20080010), U32(0x00080000), 136 | U32(0x00080010), U32(0x20080810), U32(0x00080800), U32(0x00000010), 137 | U32(0x20080810), U32(0x00080800), U32(0x00080000), U32(0x20000810), 138 | U32(0x20000010), U32(0x20080000), U32(0x00080810), U32(0x00000000), 139 | U32(0x00000800), U32(0x20000010), U32(0x20000810), U32(0x20080800), 140 | U32(0x20080000), U32(0x00000810), U32(0x00000010), U32(0x20080010), 141 | ], 142 | 143 | # nibble 6 144 | [ 145 | U32(0x00001000), U32(0x00000080), U32(0x00400080), U32(0x00400001), 146 | U32(0x00401081), U32(0x00001001), U32(0x00001080), U32(0x00000000), 147 | U32(0x00400000), U32(0x00400081), U32(0x00000081), U32(0x00401000), 148 | U32(0x00000001), U32(0x00401080), U32(0x00401000), U32(0x00000081), 149 | U32(0x00400081), U32(0x00001000), U32(0x00001001), U32(0x00401081), 150 | U32(0x00000000), U32(0x00400080), U32(0x00400001), U32(0x00001080), 151 | U32(0x00401001), U32(0x00001081), U32(0x00401080), U32(0x00000001), 152 | U32(0x00001081), U32(0x00401001), U32(0x00000080), U32(0x00400000), 153 | U32(0x00001081), U32(0x00401000), U32(0x00401001), U32(0x00000081), 154 | U32(0x00001000), U32(0x00000080), U32(0x00400000), U32(0x00401001), 155 | U32(0x00400081), U32(0x00001081), U32(0x00001080), U32(0x00000000), 156 | U32(0x00000080), U32(0x00400001), U32(0x00000001), U32(0x00400080), 157 | U32(0x00000000), U32(0x00400081), U32(0x00400080), U32(0x00001080), 158 | U32(0x00000081), U32(0x00001000), U32(0x00401081), U32(0x00400000), 159 | U32(0x00401080), U32(0x00000001), U32(0x00001001), U32(0x00401081), 160 | U32(0x00400001), U32(0x00401080), U32(0x00401000), U32(0x00001001), 161 | ], 162 | 163 | # nibble 7 164 | [ 165 | U32(0x08200020), U32(0x08208000), U32(0x00008020), U32(0x00000000), 166 | U32(0x08008000), U32(0x00200020), U32(0x08200000), U32(0x08208020), 167 | U32(0x00000020), U32(0x08000000), U32(0x00208000), U32(0x00008020), 168 | U32(0x00208020), U32(0x08008020), U32(0x08000020), U32(0x08200000), 169 | U32(0x00008000), U32(0x00208020), U32(0x00200020), U32(0x08008000), 170 | U32(0x08208020), U32(0x08000020), U32(0x00000000), U32(0x00208000), 171 | U32(0x08000000), U32(0x00200000), U32(0x08008020), U32(0x08200020), 172 | U32(0x00200000), U32(0x00008000), U32(0x08208000), U32(0x00000020), 173 | U32(0x00200000), U32(0x00008000), U32(0x08000020), U32(0x08208020), 174 | U32(0x00008020), U32(0x08000000), U32(0x00000000), U32(0x00208000), 175 | U32(0x08200020), U32(0x08008020), U32(0x08008000), U32(0x00200020), 176 | U32(0x08208000), U32(0x00000020), U32(0x00200020), U32(0x08008000), 177 | U32(0x08208020), U32(0x00200000), U32(0x08200000), U32(0x08000020), 178 | U32(0x00208000), U32(0x00008020), U32(0x08008020), U32(0x08200000), 179 | U32(0x00000020), U32(0x08208000), U32(0x00208020), U32(0x00000000), 180 | U32(0x08000000), U32(0x08200020), U32(0x00008000), U32(0x00208020), 181 | ], 182 | ] 183 | 184 | # static unsigned long des_skb[8][64]={ 185 | 186 | des_skb = \ 187 | [ 188 | # for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 189 | [ 190 | U32(0x00000000), U32(0x00000010), U32(0x20000000), U32(0x20000010), 191 | U32(0x00010000), U32(0x00010010), U32(0x20010000), U32(0x20010010), 192 | U32(0x00000800), U32(0x00000810), U32(0x20000800), U32(0x20000810), 193 | U32(0x00010800), U32(0x00010810), U32(0x20010800), U32(0x20010810), 194 | U32(0x00000020), U32(0x00000030), U32(0x20000020), U32(0x20000030), 195 | U32(0x00010020), U32(0x00010030), U32(0x20010020), U32(0x20010030), 196 | U32(0x00000820), U32(0x00000830), U32(0x20000820), U32(0x20000830), 197 | U32(0x00010820), U32(0x00010830), U32(0x20010820), U32(0x20010830), 198 | U32(0x00080000), U32(0x00080010), U32(0x20080000), U32(0x20080010), 199 | U32(0x00090000), U32(0x00090010), U32(0x20090000), U32(0x20090010), 200 | U32(0x00080800), U32(0x00080810), U32(0x20080800), U32(0x20080810), 201 | U32(0x00090800), U32(0x00090810), U32(0x20090800), U32(0x20090810), 202 | U32(0x00080020), U32(0x00080030), U32(0x20080020), U32(0x20080030), 203 | U32(0x00090020), U32(0x00090030), U32(0x20090020), U32(0x20090030), 204 | U32(0x00080820), U32(0x00080830), U32(0x20080820), U32(0x20080830), 205 | U32(0x00090820), U32(0x00090830), U32(0x20090820), U32(0x20090830), 206 | ], 207 | 208 | # for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 209 | [ 210 | U32(0x00000000), U32(0x02000000), U32(0x00002000), U32(0x02002000), 211 | U32(0x00200000), U32(0x02200000), U32(0x00202000), U32(0x02202000), 212 | U32(0x00000004), U32(0x02000004), U32(0x00002004), U32(0x02002004), 213 | U32(0x00200004), U32(0x02200004), U32(0x00202004), U32(0x02202004), 214 | U32(0x00000400), U32(0x02000400), U32(0x00002400), U32(0x02002400), 215 | U32(0x00200400), U32(0x02200400), U32(0x00202400), U32(0x02202400), 216 | U32(0x00000404), U32(0x02000404), U32(0x00002404), U32(0x02002404), 217 | U32(0x00200404), U32(0x02200404), U32(0x00202404), U32(0x02202404), 218 | U32(0x10000000), U32(0x12000000), U32(0x10002000), U32(0x12002000), 219 | U32(0x10200000), U32(0x12200000), U32(0x10202000), U32(0x12202000), 220 | U32(0x10000004), U32(0x12000004), U32(0x10002004), U32(0x12002004), 221 | U32(0x10200004), U32(0x12200004), U32(0x10202004), U32(0x12202004), 222 | U32(0x10000400), U32(0x12000400), U32(0x10002400), U32(0x12002400), 223 | U32(0x10200400), U32(0x12200400), U32(0x10202400), U32(0x12202400), 224 | U32(0x10000404), U32(0x12000404), U32(0x10002404), U32(0x12002404), 225 | U32(0x10200404), U32(0x12200404), U32(0x10202404), U32(0x12202404), 226 | ], 227 | 228 | # for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 229 | [ 230 | U32(0x00000000), U32(0x00000001), U32(0x00040000), U32(0x00040001), 231 | U32(0x01000000), U32(0x01000001), U32(0x01040000), U32(0x01040001), 232 | U32(0x00000002), U32(0x00000003), U32(0x00040002), U32(0x00040003), 233 | U32(0x01000002), U32(0x01000003), U32(0x01040002), U32(0x01040003), 234 | U32(0x00000200), U32(0x00000201), U32(0x00040200), U32(0x00040201), 235 | U32(0x01000200), U32(0x01000201), U32(0x01040200), U32(0x01040201), 236 | U32(0x00000202), U32(0x00000203), U32(0x00040202), U32(0x00040203), 237 | U32(0x01000202), U32(0x01000203), U32(0x01040202), U32(0x01040203), 238 | U32(0x08000000), U32(0x08000001), U32(0x08040000), U32(0x08040001), 239 | U32(0x09000000), U32(0x09000001), U32(0x09040000), U32(0x09040001), 240 | U32(0x08000002), U32(0x08000003), U32(0x08040002), U32(0x08040003), 241 | U32(0x09000002), U32(0x09000003), U32(0x09040002), U32(0x09040003), 242 | U32(0x08000200), U32(0x08000201), U32(0x08040200), U32(0x08040201), 243 | U32(0x09000200), U32(0x09000201), U32(0x09040200), U32(0x09040201), 244 | U32(0x08000202), U32(0x08000203), U32(0x08040202), U32(0x08040203), 245 | U32(0x09000202), U32(0x09000203), U32(0x09040202), U32(0x09040203), 246 | ], 247 | 248 | # for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 249 | [ 250 | U32(0x00000000), U32(0x00100000), U32(0x00000100), U32(0x00100100), 251 | U32(0x00000008), U32(0x00100008), U32(0x00000108), U32(0x00100108), 252 | U32(0x00001000), U32(0x00101000), U32(0x00001100), U32(0x00101100), 253 | U32(0x00001008), U32(0x00101008), U32(0x00001108), U32(0x00101108), 254 | U32(0x04000000), U32(0x04100000), U32(0x04000100), U32(0x04100100), 255 | U32(0x04000008), U32(0x04100008), U32(0x04000108), U32(0x04100108), 256 | U32(0x04001000), U32(0x04101000), U32(0x04001100), U32(0x04101100), 257 | U32(0x04001008), U32(0x04101008), U32(0x04001108), U32(0x04101108), 258 | U32(0x00020000), U32(0x00120000), U32(0x00020100), U32(0x00120100), 259 | U32(0x00020008), U32(0x00120008), U32(0x00020108), U32(0x00120108), 260 | U32(0x00021000), U32(0x00121000), U32(0x00021100), U32(0x00121100), 261 | U32(0x00021008), U32(0x00121008), U32(0x00021108), U32(0x00121108), 262 | U32(0x04020000), U32(0x04120000), U32(0x04020100), U32(0x04120100), 263 | U32(0x04020008), U32(0x04120008), U32(0x04020108), U32(0x04120108), 264 | U32(0x04021000), U32(0x04121000), U32(0x04021100), U32(0x04121100), 265 | U32(0x04021008), U32(0x04121008), U32(0x04021108), U32(0x04121108), 266 | ], 267 | 268 | # for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 269 | [ 270 | U32(0x00000000), U32(0x10000000), U32(0x00010000), U32(0x10010000), 271 | U32(0x00000004), U32(0x10000004), U32(0x00010004), U32(0x10010004), 272 | U32(0x20000000), U32(0x30000000), U32(0x20010000), U32(0x30010000), 273 | U32(0x20000004), U32(0x30000004), U32(0x20010004), U32(0x30010004), 274 | U32(0x00100000), U32(0x10100000), U32(0x00110000), U32(0x10110000), 275 | U32(0x00100004), U32(0x10100004), U32(0x00110004), U32(0x10110004), 276 | U32(0x20100000), U32(0x30100000), U32(0x20110000), U32(0x30110000), 277 | U32(0x20100004), U32(0x30100004), U32(0x20110004), U32(0x30110004), 278 | U32(0x00001000), U32(0x10001000), U32(0x00011000), U32(0x10011000), 279 | U32(0x00001004), U32(0x10001004), U32(0x00011004), U32(0x10011004), 280 | U32(0x20001000), U32(0x30001000), U32(0x20011000), U32(0x30011000), 281 | U32(0x20001004), U32(0x30001004), U32(0x20011004), U32(0x30011004), 282 | U32(0x00101000), U32(0x10101000), U32(0x00111000), U32(0x10111000), 283 | U32(0x00101004), U32(0x10101004), U32(0x00111004), U32(0x10111004), 284 | U32(0x20101000), U32(0x30101000), U32(0x20111000), U32(0x30111000), 285 | U32(0x20101004), U32(0x30101004), U32(0x20111004), U32(0x30111004), 286 | ], 287 | 288 | # for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 289 | [ 290 | U32(0x00000000), U32(0x08000000), U32(0x00000008), U32(0x08000008), 291 | U32(0x00000400), U32(0x08000400), U32(0x00000408), U32(0x08000408), 292 | U32(0x00020000), U32(0x08020000), U32(0x00020008), U32(0x08020008), 293 | U32(0x00020400), U32(0x08020400), U32(0x00020408), U32(0x08020408), 294 | U32(0x00000001), U32(0x08000001), U32(0x00000009), U32(0x08000009), 295 | U32(0x00000401), U32(0x08000401), U32(0x00000409), U32(0x08000409), 296 | U32(0x00020001), U32(0x08020001), U32(0x00020009), U32(0x08020009), 297 | U32(0x00020401), U32(0x08020401), U32(0x00020409), U32(0x08020409), 298 | U32(0x02000000), U32(0x0A000000), U32(0x02000008), U32(0x0A000008), 299 | U32(0x02000400), U32(0x0A000400), U32(0x02000408), U32(0x0A000408), 300 | U32(0x02020000), U32(0x0A020000), U32(0x02020008), U32(0x0A020008), 301 | U32(0x02020400), U32(0x0A020400), U32(0x02020408), U32(0x0A020408), 302 | U32(0x02000001), U32(0x0A000001), U32(0x02000009), U32(0x0A000009), 303 | U32(0x02000401), U32(0x0A000401), U32(0x02000409), U32(0x0A000409), 304 | U32(0x02020001), U32(0x0A020001), U32(0x02020009), U32(0x0A020009), 305 | U32(0x02020401), U32(0x0A020401), U32(0x02020409), U32(0x0A020409), 306 | ], 307 | 308 | # for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 309 | [ 310 | U32(0x00000000), U32(0x00000100), U32(0x00080000), U32(0x00080100), 311 | U32(0x01000000), U32(0x01000100), U32(0x01080000), U32(0x01080100), 312 | U32(0x00000010), U32(0x00000110), U32(0x00080010), U32(0x00080110), 313 | U32(0x01000010), U32(0x01000110), U32(0x01080010), U32(0x01080110), 314 | U32(0x00200000), U32(0x00200100), U32(0x00280000), U32(0x00280100), 315 | U32(0x01200000), U32(0x01200100), U32(0x01280000), U32(0x01280100), 316 | U32(0x00200010), U32(0x00200110), U32(0x00280010), U32(0x00280110), 317 | U32(0x01200010), U32(0x01200110), U32(0x01280010), U32(0x01280110), 318 | U32(0x00000200), U32(0x00000300), U32(0x00080200), U32(0x00080300), 319 | U32(0x01000200), U32(0x01000300), U32(0x01080200), U32(0x01080300), 320 | U32(0x00000210), U32(0x00000310), U32(0x00080210), U32(0x00080310), 321 | U32(0x01000210), U32(0x01000310), U32(0x01080210), U32(0x01080310), 322 | U32(0x00200200), U32(0x00200300), U32(0x00280200), U32(0x00280300), 323 | U32(0x01200200), U32(0x01200300), U32(0x01280200), U32(0x01280300), 324 | U32(0x00200210), U32(0x00200310), U32(0x00280210), U32(0x00280310), 325 | U32(0x01200210), U32(0x01200310), U32(0x01280210), U32(0x01280310), 326 | ], 327 | 328 | # for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 329 | [ 330 | U32(0x00000000), U32(0x04000000), U32(0x00040000), U32(0x04040000), 331 | U32(0x00000002), U32(0x04000002), U32(0x00040002), U32(0x04040002), 332 | U32(0x00002000), U32(0x04002000), U32(0x00042000), U32(0x04042000), 333 | U32(0x00002002), U32(0x04002002), U32(0x00042002), U32(0x04042002), 334 | U32(0x00000020), U32(0x04000020), U32(0x00040020), U32(0x04040020), 335 | U32(0x00000022), U32(0x04000022), U32(0x00040022), U32(0x04040022), 336 | U32(0x00002020), U32(0x04002020), U32(0x00042020), U32(0x04042020), 337 | U32(0x00002022), U32(0x04002022), U32(0x00042022), U32(0x04042022), 338 | U32(0x00000800), U32(0x04000800), U32(0x00040800), U32(0x04040800), 339 | U32(0x00000802), U32(0x04000802), U32(0x00040802), U32(0x04040802), 340 | U32(0x00002800), U32(0x04002800), U32(0x00042800), U32(0x04042800), 341 | U32(0x00002802), U32(0x04002802), U32(0x00042802), U32(0x04042802), 342 | U32(0x00000820), U32(0x04000820), U32(0x00040820), U32(0x04040820), 343 | U32(0x00000822), U32(0x04000822), U32(0x00040822), U32(0x04040822), 344 | U32(0x00002820), U32(0x04002820), U32(0x00042820), U32(0x04042820), 345 | U32(0x00002822), U32(0x04002822), U32(0x00042822), U32(0x04042822), 346 | ] 347 | 348 | ] 349 | -------------------------------------------------------------------------------- /ntlm_auth/gss_channel_bindings.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | import struct 15 | 16 | """ 17 | This is not the easiest structure to understand, ultimately this is a set structure 18 | as defined by Microsoft. Channel Binding Tokens set the SHA256 hash of the server 19 | certificate to the application_data field and then ultimately creates the MD5 hash 20 | to include in the NTLM auth from there. This class is just designed to create the 21 | bindings structure which is then used by compute_response.py to do the rest of the 22 | work. 23 | 24 | For more infor on how this works and how it is derived, this is a great link; 25 | https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/ 26 | """ 27 | 28 | 29 | class GssChannelBindingsStruct(object): 30 | INITIATOR_ADDTYPE = 'initiator_addtype' 31 | INITIATOR_ADDRESS_LENGTH = 'initiator_address_length' 32 | ACCEPTOR_ADDRTYPE = 'acceptor_addrtype' 33 | ACCEPTOR_ADDRESS_LENGTH = 'acceptor_address_length' 34 | APPLICATION_DATA_LENGTH = 'application_data_length' 35 | INITIATOR_ADDRESS = 'initiator_address' 36 | ACCEPTOR_ADDRESS = 'acceptor_address' 37 | APPLICATION_DATA = 'application_data' 38 | 39 | def __init__(self): 40 | self.fields = {} 41 | self.fields[self.INITIATOR_ADDTYPE] = 0 42 | self.fields[self.INITIATOR_ADDRESS_LENGTH] = 0 43 | self.fields[self.ACCEPTOR_ADDRTYPE] = 0 44 | self.fields[self.ACCEPTOR_ADDRESS_LENGTH] = 0 45 | self.fields[self.APPLICATION_DATA_LENGTH] = 0 46 | self.fields[self.INITIATOR_ADDRESS] = b'' 47 | self.fields[self.ACCEPTOR_ADDRESS] = b'' 48 | self.fields[self.APPLICATION_DATA] = b'' 49 | 50 | def __setitem__(self, key, value): 51 | self.fields[key] = value 52 | 53 | def get_data(self): 54 | # Set the lengths of each len field in case they have changed 55 | self.fields[self.INITIATOR_ADDRESS_LENGTH] = len(self.fields[self.INITIATOR_ADDRESS]) 56 | self.fields[self.ACCEPTOR_ADDRESS_LENGTH] = len(self.fields[self.ACCEPTOR_ADDRESS]) 57 | self.fields[self.APPLICATION_DATA_LENGTH] = len(self.fields[self.APPLICATION_DATA]) 58 | 59 | # Add all the values together to create the gss_channel_bindings_struct 60 | data = struct.pack(' or . 13 | 14 | import hmac 15 | import os 16 | import struct 17 | from ntlm_auth.compute_response import ComputeResponse 18 | from ntlm_auth.constants import NegotiateFlags, MessageTypes, NTLM_SIGNATURE, AvFlags 19 | from ntlm_auth.rc4 import ARC4 20 | from ntlm_auth.target_info import TargetInfo 21 | 22 | 23 | class NegotiateMessage(object): 24 | EXPECTED_BODY_LENGTH = 40 25 | 26 | """ 27 | [MS-NLMP] v28.0 2016-07-14 28 | 29 | 2.2.1.1 NEGOTIATE_MESSAGE 30 | The NEGOTIATE_MESSAGE defines an NTLM Negotiate message that is sent from the client to the server. 31 | This message allows the client to specify its supported NTLM options to the server. 32 | 33 | @param negotiate_flags: A NEGOTIATE structure that contains a set of bit flags represenging the client's options 34 | @param domain_name: The domain name of the user to authenticate with, default is None 35 | @param workstation: The worksation of the client machine, default is None 36 | 37 | Attributes: 38 | signature: An 8-byte character array that MUST contain the ASCII string 'NTLMSSP\0' 39 | message_type: A 32-bit unsigned integer that indicates the message type. This field must be set to 0x00000001 40 | negotiate_flags: A NEGOTIATE structure that contains a set of bit flags represenging the client's options 41 | version: Client's Windows version. For debugging only. Set when NTLMSSP_NEGOTIATE_VERSION flag is set. 42 | domain_name: A byte-array that contains the name of the client authentication domain that MUST be encoded in the negotiated character set 43 | workstation: A byte-array that contains the name of the client machine that MUST Be encoded in the negotiated character set 44 | """ 45 | 46 | def __init__(self, negotiate_flags, domain_name, workstation): 47 | self.signature = NTLM_SIGNATURE 48 | self.message_type = struct.pack(' or . 13 | 14 | import base64 15 | import struct 16 | from ntlm_auth.constants import NegotiateFlags 17 | from ntlm_auth.messages import NegotiateMessage, ChallengeMessage, AuthenticateMessage 18 | from ntlm_auth.session_security import SessionSecurity 19 | 20 | """ 21 | utility functions for Microsoft NTLM authentication 22 | 23 | References: 24 | [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol Specification 25 | http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NLMP%5D.pdf 26 | 27 | [MS-NTHT]: NTLM Over HTTP Protocol Specification 28 | http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NTHT%5D.pdf 29 | 30 | Cntlm Authentication Proxy 31 | http://cntlm.awk.cz/ 32 | 33 | NTLM Authorization Proxy Server 34 | http://sourceforge.net/projects/ntlmaps/ 35 | 36 | Optimized Attack for NTLM2 Session Response 37 | http://www.blackhat.com/presentations/bh-asia-04/bh-jp-04-pdfs/bh-jp-04-seki.pdf 38 | """ 39 | 40 | 41 | class Ntlm(object): 42 | """ 43 | Initialises the NTLM context to use when sending and receiving messages to and from the server. 44 | Supports NTLMv2 authenticate. 45 | It also brings in the ability to use signing and sealing with session_security and generate a MIC structure. 46 | 47 | @param ntlm_compatibility: The Lan Manager Compatibility Level to use with the auth message - Default 3 48 | This is set by an Administrator in the registry key 49 | 'HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel' 50 | The values correspond to the following; 51 | 0 : LM and NTLMv1 52 | 1 : LM, NTLMv1 and NTLMv1 with Extended Session Security 53 | 2 : NTLMv1 and NTLMv1 with Extended Session Security 54 | 3-5 : NTLMv2 Only 55 | 56 | Note: Values 3 to 5 are no different as the client supports the same types 57 | 58 | Attributes: 59 | negotiate_flags: A NEGOTIATE structure that contains a set of bit flags. 60 | These flags are the options the client supports and are sent in the negotiate_message 61 | ntlm_compatibility: The Lan Manager Compatibility Level, same as the input if supplied 62 | negotiate_message: A NegotiateMessage object that is sent to the server 63 | challenge_message: A ChallengeMessage object that has been created from the server response 64 | authenticate_message: An AuthenticateMessage object that is sent to the server based on the ChallengeMessage 65 | session_security: A SessionSecurity structure that can be used to sign and seal messages sent 66 | after the authentication challenge 67 | """ 68 | 69 | def __init__(self, ntlm_compatibility=3): 70 | self.ntlm_compatibility = ntlm_compatibility 71 | 72 | # Setting up our flags so the challenge message returns the target info block if supported 73 | self.negotiate_flags = \ 74 | NegotiateFlags.NTLMSSP_NEGOTIATE_TARGET_INFO | \ 75 | NegotiateFlags.NTLMSSP_NEGOTIATE_128 | \ 76 | NegotiateFlags.NTLMSSP_NEGOTIATE_56 | \ 77 | NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE | \ 78 | NegotiateFlags.NTLMSSP_NEGOTIATE_VERSION | \ 79 | NegotiateFlags.NTLMSSP_NEGOTIATE_KEY_EXCH | \ 80 | NegotiateFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \ 81 | NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN | \ 82 | NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL 83 | 84 | # Setting the message types based on the ntlm_compatibility level 85 | self._set_ntlm_compatibility_flags(self.ntlm_compatibility) 86 | 87 | self.negotiate_message = None 88 | self.challenge_message = None 89 | self.authenticate_message = None 90 | self.session_security = None 91 | 92 | def create_negotiate_message(self, domain_name=None, workstation=None): 93 | """ 94 | Create an NTLM NEGOTIATE_MESSAGE 95 | 96 | @param domain_name: The domain name of the user account we are authenticating with, default is None 97 | @param workstation: The workstation we are using to authenticate with, default is None 98 | @return: A base64 encoded string of the NEGOTIATE_MESSAGE 99 | """ 100 | self.negotiate_message = NegotiateMessage(self.negotiate_flags, domain_name, workstation) 101 | 102 | return base64.b64encode(self.negotiate_message.get_data()) 103 | 104 | def parse_challenge_message(self, msg2): 105 | """ 106 | Parse the NTLM CHALLENGE_MESSAGE from the server and add it to the Ntlm context fields 107 | 108 | @param msg2: A base64 encoded string of the CHALLENGE_MESSAGE 109 | """ 110 | msg2 = base64.b64decode(msg2) 111 | self.challenge_message = ChallengeMessage(msg2) 112 | 113 | def create_authenticate_message(self, user_name, password=None, nthash=None, lmhash=None, domain_name=None, 114 | workstation=None, server_certificate_hash=None): 115 | """ 116 | Create an NTLM AUTHENTICATE_MESSAGE based on the Ntlm context and the previous messages sent and received 117 | 118 | @param user_name: The username of the user we are trying to authenticate with 119 | @param password: The password of the user we are trying to authenticate with 120 | @param nthash: ... 121 | @param lmhash: ... 122 | @param domain_name: The domain name of the user account we are authenticated with, default is None 123 | @param workstation: The workstation we are using to authenticate with, default is None 124 | @param server_certificate_hash: The SHA256 hash string of the server certificate (DER encoded) 125 | NTLM is authenticating to. Used for Channel Binding Tokens. If nothing 126 | is supplied then the CBT hash will not be sent. 127 | See messages.py AuthenticateMessage for more details. 128 | @return: A base64 encoded string of the AUTHENTICATE_MESSAGE 129 | """ 130 | self.authenticate_message = AuthenticateMessage(user_name, password, nthash, lmhash, domain_name, workstation, 131 | self.challenge_message, self.ntlm_compatibility, 132 | server_certificate_hash) 133 | self.authenticate_message.add_mic(self.negotiate_message, self.challenge_message) 134 | 135 | # Setups up the session_security context used to sign and seal messages if wanted 136 | if self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL \ 137 | or self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN: 138 | self.session_security = SessionSecurity(struct.unpack("= 0) and (ntlm_compatibility <= 5): 145 | if ntlm_compatibility == 0: 146 | self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \ 147 | NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY 148 | elif ntlm_compatibility == 1: 149 | self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \ 150 | NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 151 | else: 152 | self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 153 | else: 154 | raise Exception("Unknown ntlm_compatibility level - expecting value between 0 and 5") 155 | -------------------------------------------------------------------------------- /ntlm_auth/rc4.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | class ARC4(object): 15 | state = None 16 | i = 0 17 | j = 0 18 | 19 | def __init__(self, key): 20 | # Split up the key into a list 21 | if isinstance(key, str): 22 | key = [ord(c) for c in key] 23 | else: 24 | key = [c for c in key] 25 | 26 | # Key-scheduling algorithm (KSA) 27 | self.state = [n for n in range(256)] 28 | j = 0 29 | for i in range(256): 30 | j = (j + self.state[i] + key[i % len(key)]) % 256 31 | self.state[i], self.state[j] = self.state[j], self.state[i] 32 | 33 | def update(self, value): 34 | chars = [] 35 | random_gen = self._random_generator() 36 | for char in value: 37 | if isinstance(value, str): 38 | byte = ord(char) 39 | else: 40 | byte = char 41 | updated_byte = byte ^ next(random_gen) 42 | chars.append(updated_byte) 43 | return bytes(bytearray(chars)) 44 | 45 | def _random_generator(self): 46 | # Pseudo-Random Generation Algorithm (PRGA) 47 | while True: 48 | self.i = (self.i + 1) % 256 49 | self.j = (self.j + self.state[self.i]) % 256 50 | self.state[self.i], self.state[self.j] = self.state[self.j], self.state[self.i] 51 | yield self.state[(self.state[self.i] + self.state[self.j]) % 256] 52 | -------------------------------------------------------------------------------- /ntlm_auth/session_security.py: -------------------------------------------------------------------------------- 1 | # This library is free software: you can redistribute it and/or 2 | # modify it under the terms of the GNU Lesser General Public 3 | # License as published by the Free Software Foundation, either 4 | # version 3 of the License, or (at your option) any later version. 5 | 6 | # This library is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | # Lesser General Public License for more details. 10 | 11 | # You should have received a copy of the GNU Lesser General Public 12 | # License along with this library. If not, see or . 13 | 14 | import binascii 15 | import hmac 16 | import struct 17 | import ntlm_auth.compute_keys as compkeys 18 | from ntlm_auth.constants import NegotiateFlags, SignSealConstants 19 | from ntlm_auth.rc4 import ARC4 20 | 21 | 22 | class _NtlmMessageSignature1(object): 23 | EXPECTED_BODY_LENGTH = 16 24 | 25 | """ 26 | [MS-NLMP] v28.0 2016-07-14 27 | 28 | 2.2.2.9.1 NTLMSSP_MESSAGE_SIGNATURE 29 | This version of the NTLMSSP_MESSAGE_SIGNATURE structure MUST be used when the 30 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is not negotiated. 31 | 32 | :param random_pad: A 4-byte array that contains the random pad for the emssage 33 | :param checksum: A 4-byte array that contains the checksum for the message 34 | :param seq_num: A 32-bit unsigned integer that contains the NTLM sequence number for this application message 35 | """ 36 | 37 | def __init__(self, random_pad, checksum, seq_num): 38 | self.version = struct.pack(" 1: 29 | raise TypeError('expected at most 1 arguments, got %d' % len(args)) 30 | try: 31 | self.__end 32 | except AttributeError: 33 | self.clear() 34 | self.update(*args, **kwds) 35 | 36 | def clear(self): 37 | self.__end = end = [] 38 | end += [None, end, end] # sentinel node for doubly linked list 39 | self.__map = {} # key --> [key, prev, next] 40 | dict.clear(self) 41 | 42 | def __setitem__(self, key, value): 43 | if key not in self: 44 | end = self.__end 45 | curr = end[1] 46 | curr[2] = end[1] = self.__map[key] = [key, curr, end] 47 | dict.__setitem__(self, key, value) 48 | 49 | def __delitem__(self, key): 50 | dict.__delitem__(self, key) 51 | key, prev, next = self.__map.pop(key) 52 | prev[2] = next 53 | next[1] = prev 54 | 55 | def __iter__(self): 56 | end = self.__end 57 | curr = end[2] 58 | while curr is not end: 59 | yield curr[0] 60 | curr = curr[2] 61 | 62 | def __reversed__(self): 63 | end = self.__end 64 | curr = end[1] 65 | while curr is not end: 66 | yield curr[0] 67 | curr = curr[1] 68 | 69 | def popitem(self, last=True): 70 | if not self: 71 | raise KeyError('dictionary is empty') 72 | if last: 73 | key = reversed(self).next() 74 | else: 75 | key = iter(self).next() 76 | value = self.pop(key) 77 | return key, value 78 | 79 | def __reduce__(self): 80 | items = [[k, self[k]] for k in self] 81 | tmp = self.__map, self.__end 82 | del self.__map, self.__end 83 | inst_dict = vars(self).copy() 84 | self.__map, self.__end = tmp 85 | if inst_dict: 86 | return (self.__class__, (items,), inst_dict) 87 | return self.__class__, (items,) 88 | 89 | def keys(self): 90 | return list(self) 91 | 92 | setdefault = DictMixin.setdefault 93 | update = DictMixin.update 94 | pop = DictMixin.pop 95 | values = DictMixin.values 96 | items = DictMixin.items 97 | iterkeys = DictMixin.iterkeys 98 | itervalues = DictMixin.itervalues 99 | iteritems = DictMixin.iteritems 100 | 101 | def __repr__(self): 102 | if not self: 103 | return '%s()' % (self.__class__.__name__,) 104 | return '%s(%r)' % (self.__class__.__name__, self.items()) 105 | 106 | def copy(self): 107 | return self.__class__(self) 108 | 109 | @classmethod 110 | def fromkeys(cls, iterable, value=None): 111 | d = cls() 112 | for key in iterable: 113 | d[key] = value 114 | return d 115 | 116 | def __eq__(self, other): 117 | if isinstance(other, OrderedDict): 118 | if len(self) != len(other): 119 | return False 120 | for p, q in zip(self.items(), other.items()): 121 | if p != q: 122 | return False 123 | return True 124 | return dict.__eq__(self, other) 125 | 126 | def __ne__(self, other): 127 | return not self == other 128 | -------------------------------------------------------------------------------- /relay.py: -------------------------------------------------------------------------------- 1 | buffer_size = 4096 2 | delay = 0.0001 3 | socks_server_reply_success = b'\x00\x5a\xff\xff\xff\xff\xff\xff' 4 | socks_server_reply_fail = b'\x00\x5b\xff\xff\xff\xff\xff\xff' 5 | relay_timeout = 160 6 | banner = b'RPIVOT' 7 | banner_response = b'TUNNELRDY' 8 | 9 | COMMAND_CHANNEL = 0 10 | 11 | CHANNEL_CLOSE_CMD = b'\xcc' 12 | CHANNEL_OPEN_CMD = b'\xdd' 13 | FORWARD_CONNECTION_SUCCESS = b'\xee' 14 | FORWARD_CONNECTION_FAILURE = b'\xff' 15 | CLOSE_RELAY = b'\xc4' 16 | PING_CMD = b'\x70' 17 | 18 | cmd_names = { 19 | b'\xcc': b'CHANNEL_CLOSE_CMD', 20 | b'\xdd': b'CHANNEL_OPEN_CMD', 21 | b'\xee': b'FORWARD_CONNECTION_SUCCESS', 22 | b'\xff': b'FORWARD_CONNECTION_FAILURE', 23 | b'\xc4': b'CLOSE_RELAY', 24 | b'\x70': b'PING_CMD' 25 | } 26 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import socket 4 | import select 5 | import sys 6 | import time 7 | import struct 8 | from struct import pack, unpack 9 | import random 10 | import errno 11 | import relay 12 | import threading 13 | import optparse 14 | from common import create_logger, b, to_hex, ls, RelayMainError, Relay 15 | 16 | 17 | class RelayServer(Relay): 18 | 19 | def __init__(self, host, port, command_socket): 20 | super(RelayServer, self).__init__(command_socket) 21 | self.pending_socks_clients = [] 22 | 23 | self.ping_thread = threading.Thread(target=self.ping_worker, name='Ping') 24 | self.ping_thread.start() 25 | 26 | self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 27 | self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 28 | 29 | try: 30 | self.server.bind((host, port)) 31 | self.server.listen(2000) 32 | except socket.error as err: 33 | (code, msg) = err.args 34 | log.error('Error binding socks proxy: {0}.\nClosing socket...'.format(msg)) 35 | self.command_socket.close() 36 | raise 37 | 38 | # 39 | # Common methods 40 | # 41 | 42 | def ping_worker(self): 43 | while True: 44 | time.sleep(self.ping_delay) 45 | current_time = time.time() 46 | 47 | if self.remote_side_is_down: 48 | log.debug('Remote side is down, exiting...') 49 | return 50 | 51 | if current_time - self.last_ping > self.relay_timeout: 52 | log.error('No response from the client for {0} seconds. ' 53 | 'Restarting relay...'.format(self.relay_timeout)) 54 | self.command_socket.close() 55 | return 56 | 57 | try: 58 | self.send_proxy_cmd(relay.PING_CMD) 59 | except socket.error as err: 60 | (code, msg) = err.args 61 | log.debug('{0} {1}. Closing socket...'.format(code, msg)) 62 | self.command_socket.close() 63 | 64 | except RelayMainError as err: 65 | log.debug('{}. Exiting...'.format(err)) 66 | self.shutdown() 67 | 68 | def generate_channel_id(self): 69 | channel_ids = self.channels.keys() 70 | 71 | while True: 72 | rint = random.randint(1, 65535) 73 | if rint not in channel_ids: 74 | return rint 75 | 76 | def set_channel(self, sock): 77 | """ 78 | @return: id of the new channel 79 | """ 80 | return self._set_channel(sock, self.generate_channel_id()) 81 | 82 | # 83 | # Handle commands 84 | # 85 | 86 | def close_channel_hdl(self, channel_id): 87 | log.debug('[channel {0}] Closing...'.format(channel_id)) 88 | 89 | if channel_id not in self.channels: 90 | log.warning('[channel {0}] Channel already closed'.format(channel_id)) 91 | return 92 | 93 | sock_to_close = self.channels[channel_id] 94 | self.input_connections.remove(sock_to_close) 95 | self.unset_channel(channel_id) 96 | sock_to_close.close() 97 | 98 | def forward_connection_success_hdl(self, channel_id): 99 | if channel_id not in self.channels: 100 | log.debug('[channel {}] Forward connection successful. ' 101 | 'But channel already closed'.format(channel_id)) 102 | return 103 | 104 | log.debug('[channel {}] Forward connection successful. Sending success replay...'.format(channel_id)) 105 | 106 | try: 107 | self.channels[channel_id].send(relay.socks_server_reply_success) 108 | except socket.error as err: 109 | (code, msg) = err.args 110 | log.error('[channel {}] Socket error on replying SUCCESS to a SOCKS client. ' 111 | 'Code {}. Msg {}'.format(channel_id, code, msg)) 112 | log.debug('[channel {0}] Closing connection and sending channel close cmd to remote side') 113 | sock = self.channels[channel_id] 114 | self.input_connections.remove(sock) 115 | self.unset_channel(channel_id) 116 | 117 | try: 118 | sock.close() 119 | except socket.error: 120 | log.debug('[channel {}] Error on closing socket'.format(channel_id)) 121 | 122 | self.send_proxy_cmd(relay.CHANNEL_CLOSE_CMD, channel_id) 123 | 124 | def forward_connection_failue_hdl(self, channel_id): 125 | if channel_id not in self.channels: 126 | log.warning('[channel {}] Channel already closed'.format(channel_id)) 127 | return 128 | 129 | log.debug('[channel {}] Forward connection failed. Sending fail replay...'.format(channel_id)) 130 | sock = self.channels[channel_id] 131 | try: 132 | sock.send(relay.socks_server_reply_fail) 133 | except socket.error as err: 134 | (code, msg) = err.args 135 | log.error('[channel {}] Socket error on replying FAILURE to a SOCKS client. ' 136 | 'Code {}. Msg {}'.format(channel_id, code, msg)) 137 | 138 | self.input_connections.remove(sock) 139 | self.unset_channel(channel_id) 140 | try: 141 | sock.close() 142 | except socket.error as err: 143 | (code, msg) = err.args 144 | log.debug('channel {}] Error on closing socket: Code {}. Msg {}'.format(channel_id, code, msg)) 145 | 146 | def ping_command_hdl(self): 147 | self.last_ping = time.time() 148 | 149 | # 150 | # SOCKS client's methods 151 | # 152 | 153 | def handle_new_socks_connection(self, sock): 154 | """ 155 | @return: 156 | @raise: RelayMainError 157 | """ 158 | log.debug('Setting up a new connection with a client program') 159 | 160 | try: 161 | # Getting socks header from a client program 162 | data = sock.recv(9) 163 | if len(data) != 9 or b(data[-1]) != b'\x00': 164 | raise RelayMainError('Corrupted header: {}'.format(data)) 165 | 166 | except socket.error as err: 167 | (code, msg) = err.args 168 | raise RelayMainError('Socket error: {} {}'.format(errno.errorcode[code], msg)) 169 | 170 | if len(data) == 0: 171 | raise RelayMainError('SOCKS client prematurely ended connection') 172 | 173 | return self.parse_socks_header(data) 174 | 175 | # 176 | # ... 177 | # 178 | 179 | def main_loop(self): 180 | 181 | self.input_connections.append(self.server) 182 | 183 | while True: 184 | time.sleep(relay.delay) 185 | 186 | try: 187 | log.debug("Active channels: {0}".format(ls(self.channels.keys()))) 188 | ready_to_read, _, _ = select.select(self.input_connections, [], []) 189 | except socket.error as err: 190 | (code, msg) = err.args 191 | raise RelayMainError('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) 192 | 193 | except KeyboardInterrupt: 194 | log.debug('SIGINT received. Closing relay and exiting...') 195 | self.shutdown() 196 | sys.exit(1) 197 | 198 | # Running over sockets from self.input_connections that have something to read from 199 | for inp_sock in ready_to_read: 200 | if inp_sock == self.server: 201 | socks_client, client_addr = self.server.accept() 202 | log.info("New connection from a client program {}:{}".format(client_addr[0], client_addr[1])) 203 | self.input_connections.append(socks_client) 204 | self.pending_socks_clients.append(socks_client) 205 | 206 | elif inp_sock == self.command_socket: 207 | try: 208 | log.debug("Processing proxy client command...") 209 | self.manage_proxy_socket() 210 | except Exception as err: 211 | log.error(err) 212 | log.warning('Closing connection with remote side and exiting loop') 213 | self.shutdown() 214 | return 215 | 216 | elif inp_sock in self.pending_socks_clients: 217 | self.pending_socks_clients.remove(inp_sock) 218 | try: 219 | # setting up a connection with a client program 220 | ip, port = self.handle_new_socks_connection(inp_sock) 221 | except RelayMainError as err: 222 | log.error('Error while openning a connection with a client program: {}'.format(err)) 223 | log.debug("Closing SOCKS client connection {0}".format(inp_sock)) 224 | self.input_connections.remove(inp_sock) 225 | inp_sock.close() 226 | continue 227 | 228 | new_channel_id = self.set_channel(inp_sock) 229 | log.debug('Sending command to a proxy client to open a channel {0} ' 230 | 'for a new client program'.format(new_channel_id)) 231 | self.send_proxy_cmd(relay.CHANNEL_OPEN_CMD, new_channel_id, ip, port) 232 | 233 | elif inp_sock in self.id_by_socket: 234 | self.manage_socks_client_socket(inp_sock) 235 | 236 | else: 237 | log.debug('Active socket {0} does not belong to any channel. Closing it'.format(inp_sock)) 238 | inp_sock.close() 239 | 240 | 241 | def run_server(host, port, proxy_host, proxy_port): 242 | log.info('============ Start proxy server ============') 243 | 244 | while True: 245 | serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 246 | serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 247 | 248 | try: 249 | serversock.bind((host, port)) 250 | serversock.listen(5) 251 | except socket.error: 252 | log.error('Exception binding socket at {0}:{1}'.format(host, port)) 253 | time.sleep(1) 254 | break 255 | 256 | try: 257 | (backconnect, address) = serversock.accept() 258 | except KeyboardInterrupt: 259 | log.error('SIGINT received. Shutting down') 260 | sys.exit(1) 261 | 262 | log.info('New connection from client {0}:{1}'.format(address[0], address[1])) 263 | serversock.close() 264 | 265 | try: 266 | banner_rcv = backconnect.recv(4096) 267 | if banner_rcv != relay.banner: 268 | log.error("Wrong banner {0} from the client. Closing connection".format(repr(banner_rcv))) 269 | backconnect.close() 270 | continue 271 | backconnect.send(relay.banner_response) 272 | except socket.error as err: 273 | (code, msg) = err.args 274 | log.error('Caught socket error trying to establish connection with RPIVOT client. ' 275 | 'Code {0}. Msg {1}'.format(code, msg)) 276 | continue 277 | 278 | try: 279 | server = RelayServer(proxy_host, int(proxy_port), backconnect) 280 | 281 | except socket.error: 282 | log.error('Error on running relay server. Restarting...') 283 | continue 284 | try: 285 | server.main_loop() 286 | except RelayMainError as err: 287 | log.error('RelayMainError in main_loop(): {}'.format(err)) 288 | log.info('Restarting relay...') 289 | server.server.close() 290 | continue 291 | 292 | except KeyboardInterrupt: 293 | log.error("Ctrl C - Stopping server...") 294 | sys.exit(1) 295 | 296 | 297 | def main(): 298 | global log 299 | 300 | parser = optparse.OptionParser(description='Reverse socks server') 301 | parser.add_option('--server-ip', action="store", dest='server_ip', default='0.0.0.0') 302 | parser.add_option('--server-port', action="store", dest='server_port', default='9999') 303 | parser.add_option('--proxy-ip', action="store", dest='proxy_ip', default='127.0.0.1') 304 | parser.add_option('--proxy-port', action="store", dest='proxy_port', default='1080') 305 | parser.add_option('--verbose', action="store_true", dest="verbose", default=False) 306 | parser.add_option('--logfile', action="store", dest="logfile", default=None) 307 | 308 | cmd_options = parser.parse_args()[0] 309 | 310 | log = create_logger(__name__, True, cmd_options.verbose, cmd_options.logfile) 311 | run_server(cmd_options.server_ip, int(cmd_options.server_port), cmd_options.proxy_ip, int(cmd_options.proxy_port)) 312 | 313 | 314 | if __name__ == "__main__": 315 | main() 316 | -------------------------------------------------------------------------------- /six.py: -------------------------------------------------------------------------------- 1 | """Utilities for writing code that runs on Python 2 and 3""" 2 | 3 | # Copyright (c) 2010-2015 Benjamin Peterson 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from __future__ import absolute_import 24 | 25 | import functools 26 | import itertools 27 | import operator 28 | import sys 29 | import types 30 | 31 | __author__ = "Benjamin Peterson " 32 | __version__ = "1.10.0" 33 | 34 | 35 | # Useful for very coarse version differentiation. 36 | PY2 = sys.version_info[0] == 2 37 | PY3 = sys.version_info[0] == 3 38 | PY34 = sys.version_info[0:2] >= (3, 4) 39 | 40 | if PY3: 41 | string_types = str, 42 | integer_types = int, 43 | class_types = type, 44 | text_type = str 45 | binary_type = bytes 46 | 47 | MAXSIZE = sys.maxsize 48 | else: 49 | string_types = basestring, 50 | integer_types = (int, long) 51 | class_types = (type, types.ClassType) 52 | text_type = unicode 53 | binary_type = str 54 | 55 | if sys.platform.startswith("java"): 56 | # Jython always uses 32 bits. 57 | MAXSIZE = int((1 << 31) - 1) 58 | else: 59 | # It's possible to have sizeof(long) != sizeof(Py_ssize_t). 60 | class X(object): 61 | 62 | def __len__(self): 63 | return 1 << 31 64 | try: 65 | len(X()) 66 | except OverflowError: 67 | # 32-bit 68 | MAXSIZE = int((1 << 31) - 1) 69 | else: 70 | # 64-bit 71 | MAXSIZE = int((1 << 63) - 1) 72 | del X 73 | 74 | 75 | def _add_doc(func, doc): 76 | """Add documentation to a function.""" 77 | func.__doc__ = doc 78 | 79 | 80 | def _import_module(name): 81 | """Import module, returning the module after the last dot.""" 82 | __import__(name) 83 | return sys.modules[name] 84 | 85 | 86 | class _LazyDescr(object): 87 | 88 | def __init__(self, name): 89 | self.name = name 90 | 91 | def __get__(self, obj, tp): 92 | result = self._resolve() 93 | setattr(obj, self.name, result) # Invokes __set__. 94 | try: 95 | # This is a bit ugly, but it avoids running this again by 96 | # removing this descriptor. 97 | delattr(obj.__class__, self.name) 98 | except AttributeError: 99 | pass 100 | return result 101 | 102 | 103 | class MovedModule(_LazyDescr): 104 | 105 | def __init__(self, name, old, new=None): 106 | super(MovedModule, self).__init__(name) 107 | if PY3: 108 | if new is None: 109 | new = name 110 | self.mod = new 111 | else: 112 | self.mod = old 113 | 114 | def _resolve(self): 115 | return _import_module(self.mod) 116 | 117 | def __getattr__(self, attr): 118 | _module = self._resolve() 119 | value = getattr(_module, attr) 120 | setattr(self, attr, value) 121 | return value 122 | 123 | 124 | class _LazyModule(types.ModuleType): 125 | 126 | def __init__(self, name): 127 | super(_LazyModule, self).__init__(name) 128 | self.__doc__ = self.__class__.__doc__ 129 | 130 | def __dir__(self): 131 | attrs = ["__doc__", "__name__"] 132 | attrs += [attr.name for attr in self._moved_attributes] 133 | return attrs 134 | 135 | # Subclasses should override this 136 | _moved_attributes = [] 137 | 138 | 139 | class MovedAttribute(_LazyDescr): 140 | 141 | def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): 142 | super(MovedAttribute, self).__init__(name) 143 | if PY3: 144 | if new_mod is None: 145 | new_mod = name 146 | self.mod = new_mod 147 | if new_attr is None: 148 | if old_attr is None: 149 | new_attr = name 150 | else: 151 | new_attr = old_attr 152 | self.attr = new_attr 153 | else: 154 | self.mod = old_mod 155 | if old_attr is None: 156 | old_attr = name 157 | self.attr = old_attr 158 | 159 | def _resolve(self): 160 | module = _import_module(self.mod) 161 | return getattr(module, self.attr) 162 | 163 | 164 | class _SixMetaPathImporter(object): 165 | 166 | """ 167 | A meta path importer to import six.moves and its submodules. 168 | 169 | This class implements a PEP302 finder and loader. It should be compatible 170 | with Python 2.5 and all existing versions of Python3 171 | """ 172 | 173 | def __init__(self, six_module_name): 174 | self.name = six_module_name 175 | self.known_modules = {} 176 | 177 | def _add_module(self, mod, *fullnames): 178 | for fullname in fullnames: 179 | self.known_modules[self.name + "." + fullname] = mod 180 | 181 | def _get_module(self, fullname): 182 | return self.known_modules[self.name + "." + fullname] 183 | 184 | def find_module(self, fullname, path=None): 185 | if fullname in self.known_modules: 186 | return self 187 | return None 188 | 189 | def __get_module(self, fullname): 190 | try: 191 | return self.known_modules[fullname] 192 | except KeyError: 193 | raise ImportError("This loader does not know module " + fullname) 194 | 195 | def load_module(self, fullname): 196 | try: 197 | # in case of a reload 198 | return sys.modules[fullname] 199 | except KeyError: 200 | pass 201 | mod = self.__get_module(fullname) 202 | if isinstance(mod, MovedModule): 203 | mod = mod._resolve() 204 | else: 205 | mod.__loader__ = self 206 | sys.modules[fullname] = mod 207 | return mod 208 | 209 | def is_package(self, fullname): 210 | """ 211 | Return true, if the named module is a package. 212 | 213 | We need this method to get correct spec objects with 214 | Python 3.4 (see PEP451) 215 | """ 216 | return hasattr(self.__get_module(fullname), "__path__") 217 | 218 | def get_code(self, fullname): 219 | """Return None 220 | 221 | Required, if is_package is implemented""" 222 | self.__get_module(fullname) # eventually raises ImportError 223 | return None 224 | get_source = get_code # same as get_code 225 | 226 | _importer = _SixMetaPathImporter(__name__) 227 | 228 | 229 | class _MovedItems(_LazyModule): 230 | 231 | """Lazy loading of moved objects""" 232 | __path__ = [] # mark as package 233 | 234 | 235 | _moved_attributes = [ 236 | MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), 237 | MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), 238 | MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), 239 | MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), 240 | MovedAttribute("intern", "__builtin__", "sys"), 241 | MovedAttribute("map", "itertools", "builtins", "imap", "map"), 242 | MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), 243 | MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), 244 | MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), 245 | MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), 246 | MovedAttribute("reduce", "__builtin__", "functools"), 247 | MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), 248 | MovedAttribute("StringIO", "StringIO", "io"), 249 | MovedAttribute("UserDict", "UserDict", "collections"), 250 | MovedAttribute("UserList", "UserList", "collections"), 251 | MovedAttribute("UserString", "UserString", "collections"), 252 | MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), 253 | MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), 254 | MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), 255 | MovedModule("builtins", "__builtin__"), 256 | MovedModule("configparser", "ConfigParser"), 257 | MovedModule("copyreg", "copy_reg"), 258 | MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), 259 | MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), 260 | MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), 261 | MovedModule("http_cookies", "Cookie", "http.cookies"), 262 | MovedModule("html_entities", "htmlentitydefs", "html.entities"), 263 | MovedModule("html_parser", "HTMLParser", "html.parser"), 264 | MovedModule("http_client", "httplib", "http.client"), 265 | MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), 266 | MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), 267 | MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), 268 | MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), 269 | MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), 270 | MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), 271 | MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), 272 | MovedModule("cPickle", "cPickle", "pickle"), 273 | MovedModule("queue", "Queue"), 274 | MovedModule("reprlib", "repr"), 275 | MovedModule("socketserver", "SocketServer"), 276 | MovedModule("_thread", "thread", "_thread"), 277 | MovedModule("tkinter", "Tkinter"), 278 | MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), 279 | MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), 280 | MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), 281 | MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), 282 | MovedModule("tkinter_tix", "Tix", "tkinter.tix"), 283 | MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), 284 | MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), 285 | MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), 286 | MovedModule("tkinter_colorchooser", "tkColorChooser", 287 | "tkinter.colorchooser"), 288 | MovedModule("tkinter_commondialog", "tkCommonDialog", 289 | "tkinter.commondialog"), 290 | MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), 291 | MovedModule("tkinter_font", "tkFont", "tkinter.font"), 292 | MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), 293 | MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", 294 | "tkinter.simpledialog"), 295 | MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), 296 | MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), 297 | MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), 298 | MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), 299 | MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), 300 | MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), 301 | ] 302 | # Add windows specific modules. 303 | if sys.platform == "win32": 304 | _moved_attributes += [ 305 | MovedModule("winreg", "_winreg"), 306 | ] 307 | 308 | for attr in _moved_attributes: 309 | setattr(_MovedItems, attr.name, attr) 310 | if isinstance(attr, MovedModule): 311 | _importer._add_module(attr, "moves." + attr.name) 312 | del attr 313 | 314 | _MovedItems._moved_attributes = _moved_attributes 315 | 316 | moves = _MovedItems(__name__ + ".moves") 317 | _importer._add_module(moves, "moves") 318 | 319 | 320 | class Module_six_moves_urllib_parse(_LazyModule): 321 | 322 | """Lazy loading of moved objects in six.moves.urllib_parse""" 323 | 324 | 325 | _urllib_parse_moved_attributes = [ 326 | MovedAttribute("ParseResult", "urlparse", "urllib.parse"), 327 | MovedAttribute("SplitResult", "urlparse", "urllib.parse"), 328 | MovedAttribute("parse_qs", "urlparse", "urllib.parse"), 329 | MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), 330 | MovedAttribute("urldefrag", "urlparse", "urllib.parse"), 331 | MovedAttribute("urljoin", "urlparse", "urllib.parse"), 332 | MovedAttribute("urlparse", "urlparse", "urllib.parse"), 333 | MovedAttribute("urlsplit", "urlparse", "urllib.parse"), 334 | MovedAttribute("urlunparse", "urlparse", "urllib.parse"), 335 | MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), 336 | MovedAttribute("quote", "urllib", "urllib.parse"), 337 | MovedAttribute("quote_plus", "urllib", "urllib.parse"), 338 | MovedAttribute("unquote", "urllib", "urllib.parse"), 339 | MovedAttribute("unquote_plus", "urllib", "urllib.parse"), 340 | MovedAttribute("urlencode", "urllib", "urllib.parse"), 341 | MovedAttribute("splitquery", "urllib", "urllib.parse"), 342 | MovedAttribute("splittag", "urllib", "urllib.parse"), 343 | MovedAttribute("splituser", "urllib", "urllib.parse"), 344 | MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), 345 | MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), 346 | MovedAttribute("uses_params", "urlparse", "urllib.parse"), 347 | MovedAttribute("uses_query", "urlparse", "urllib.parse"), 348 | MovedAttribute("uses_relative", "urlparse", "urllib.parse"), 349 | ] 350 | for attr in _urllib_parse_moved_attributes: 351 | setattr(Module_six_moves_urllib_parse, attr.name, attr) 352 | del attr 353 | 354 | Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes 355 | 356 | _importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), 357 | "moves.urllib_parse", "moves.urllib.parse") 358 | 359 | 360 | class Module_six_moves_urllib_error(_LazyModule): 361 | 362 | """Lazy loading of moved objects in six.moves.urllib_error""" 363 | 364 | 365 | _urllib_error_moved_attributes = [ 366 | MovedAttribute("URLError", "urllib2", "urllib.error"), 367 | MovedAttribute("HTTPError", "urllib2", "urllib.error"), 368 | MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), 369 | ] 370 | for attr in _urllib_error_moved_attributes: 371 | setattr(Module_six_moves_urllib_error, attr.name, attr) 372 | del attr 373 | 374 | Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes 375 | 376 | _importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), 377 | "moves.urllib_error", "moves.urllib.error") 378 | 379 | 380 | class Module_six_moves_urllib_request(_LazyModule): 381 | 382 | """Lazy loading of moved objects in six.moves.urllib_request""" 383 | 384 | 385 | _urllib_request_moved_attributes = [ 386 | MovedAttribute("urlopen", "urllib2", "urllib.request"), 387 | MovedAttribute("install_opener", "urllib2", "urllib.request"), 388 | MovedAttribute("build_opener", "urllib2", "urllib.request"), 389 | MovedAttribute("pathname2url", "urllib", "urllib.request"), 390 | MovedAttribute("url2pathname", "urllib", "urllib.request"), 391 | MovedAttribute("getproxies", "urllib", "urllib.request"), 392 | MovedAttribute("Request", "urllib2", "urllib.request"), 393 | MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), 394 | MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), 395 | MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), 396 | MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), 397 | MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), 398 | MovedAttribute("BaseHandler", "urllib2", "urllib.request"), 399 | MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), 400 | MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), 401 | MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), 402 | MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), 403 | MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), 404 | MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), 405 | MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), 406 | MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), 407 | MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), 408 | MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), 409 | MovedAttribute("FileHandler", "urllib2", "urllib.request"), 410 | MovedAttribute("FTPHandler", "urllib2", "urllib.request"), 411 | MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), 412 | MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), 413 | MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), 414 | MovedAttribute("urlretrieve", "urllib", "urllib.request"), 415 | MovedAttribute("urlcleanup", "urllib", "urllib.request"), 416 | MovedAttribute("URLopener", "urllib", "urllib.request"), 417 | MovedAttribute("FancyURLopener", "urllib", "urllib.request"), 418 | MovedAttribute("proxy_bypass", "urllib", "urllib.request"), 419 | ] 420 | for attr in _urllib_request_moved_attributes: 421 | setattr(Module_six_moves_urllib_request, attr.name, attr) 422 | del attr 423 | 424 | Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes 425 | 426 | _importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), 427 | "moves.urllib_request", "moves.urllib.request") 428 | 429 | 430 | class Module_six_moves_urllib_response(_LazyModule): 431 | 432 | """Lazy loading of moved objects in six.moves.urllib_response""" 433 | 434 | 435 | _urllib_response_moved_attributes = [ 436 | MovedAttribute("addbase", "urllib", "urllib.response"), 437 | MovedAttribute("addclosehook", "urllib", "urllib.response"), 438 | MovedAttribute("addinfo", "urllib", "urllib.response"), 439 | MovedAttribute("addinfourl", "urllib", "urllib.response"), 440 | ] 441 | for attr in _urllib_response_moved_attributes: 442 | setattr(Module_six_moves_urllib_response, attr.name, attr) 443 | del attr 444 | 445 | Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes 446 | 447 | _importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), 448 | "moves.urllib_response", "moves.urllib.response") 449 | 450 | 451 | class Module_six_moves_urllib_robotparser(_LazyModule): 452 | 453 | """Lazy loading of moved objects in six.moves.urllib_robotparser""" 454 | 455 | 456 | _urllib_robotparser_moved_attributes = [ 457 | MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), 458 | ] 459 | for attr in _urllib_robotparser_moved_attributes: 460 | setattr(Module_six_moves_urllib_robotparser, attr.name, attr) 461 | del attr 462 | 463 | Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes 464 | 465 | _importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), 466 | "moves.urllib_robotparser", "moves.urllib.robotparser") 467 | 468 | 469 | class Module_six_moves_urllib(types.ModuleType): 470 | 471 | """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" 472 | __path__ = [] # mark as package 473 | parse = _importer._get_module("moves.urllib_parse") 474 | error = _importer._get_module("moves.urllib_error") 475 | request = _importer._get_module("moves.urllib_request") 476 | response = _importer._get_module("moves.urllib_response") 477 | robotparser = _importer._get_module("moves.urllib_robotparser") 478 | 479 | def __dir__(self): 480 | return ['parse', 'error', 'request', 'response', 'robotparser'] 481 | 482 | _importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), 483 | "moves.urllib") 484 | 485 | 486 | def add_move(move): 487 | """Add an item to six.moves.""" 488 | setattr(_MovedItems, move.name, move) 489 | 490 | 491 | def remove_move(name): 492 | """Remove item from six.moves.""" 493 | try: 494 | delattr(_MovedItems, name) 495 | except AttributeError: 496 | try: 497 | del moves.__dict__[name] 498 | except KeyError: 499 | raise AttributeError("no such move, %r" % (name,)) 500 | 501 | 502 | if PY3: 503 | _meth_func = "__func__" 504 | _meth_self = "__self__" 505 | 506 | _func_closure = "__closure__" 507 | _func_code = "__code__" 508 | _func_defaults = "__defaults__" 509 | _func_globals = "__globals__" 510 | else: 511 | _meth_func = "im_func" 512 | _meth_self = "im_self" 513 | 514 | _func_closure = "func_closure" 515 | _func_code = "func_code" 516 | _func_defaults = "func_defaults" 517 | _func_globals = "func_globals" 518 | 519 | 520 | try: 521 | advance_iterator = next 522 | except NameError: 523 | def advance_iterator(it): 524 | return it.next() 525 | next = advance_iterator 526 | 527 | 528 | try: 529 | callable = callable 530 | except NameError: 531 | def callable(obj): 532 | return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) 533 | 534 | 535 | if PY3: 536 | def get_unbound_function(unbound): 537 | return unbound 538 | 539 | create_bound_method = types.MethodType 540 | 541 | def create_unbound_method(func, cls): 542 | return func 543 | 544 | Iterator = object 545 | else: 546 | def get_unbound_function(unbound): 547 | return unbound.im_func 548 | 549 | def create_bound_method(func, obj): 550 | return types.MethodType(func, obj, obj.__class__) 551 | 552 | def create_unbound_method(func, cls): 553 | return types.MethodType(func, None, cls) 554 | 555 | class Iterator(object): 556 | 557 | def next(self): 558 | return type(self).__next__(self) 559 | 560 | callable = callable 561 | _add_doc(get_unbound_function, 562 | """Get the function out of a possibly unbound function""") 563 | 564 | 565 | get_method_function = operator.attrgetter(_meth_func) 566 | get_method_self = operator.attrgetter(_meth_self) 567 | get_function_closure = operator.attrgetter(_func_closure) 568 | get_function_code = operator.attrgetter(_func_code) 569 | get_function_defaults = operator.attrgetter(_func_defaults) 570 | get_function_globals = operator.attrgetter(_func_globals) 571 | 572 | 573 | if PY3: 574 | def iterkeys(d, **kw): 575 | return iter(d.keys(**kw)) 576 | 577 | def itervalues(d, **kw): 578 | return iter(d.values(**kw)) 579 | 580 | def iteritems(d, **kw): 581 | return iter(d.items(**kw)) 582 | 583 | def iterlists(d, **kw): 584 | return iter(d.lists(**kw)) 585 | 586 | viewkeys = operator.methodcaller("keys") 587 | 588 | viewvalues = operator.methodcaller("values") 589 | 590 | viewitems = operator.methodcaller("items") 591 | else: 592 | def iterkeys(d, **kw): 593 | return d.iterkeys(**kw) 594 | 595 | def itervalues(d, **kw): 596 | return d.itervalues(**kw) 597 | 598 | def iteritems(d, **kw): 599 | return d.iteritems(**kw) 600 | 601 | def iterlists(d, **kw): 602 | return d.iterlists(**kw) 603 | 604 | viewkeys = operator.methodcaller("viewkeys") 605 | 606 | viewvalues = operator.methodcaller("viewvalues") 607 | 608 | viewitems = operator.methodcaller("viewitems") 609 | 610 | _add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") 611 | _add_doc(itervalues, "Return an iterator over the values of a dictionary.") 612 | _add_doc(iteritems, 613 | "Return an iterator over the (key, value) pairs of a dictionary.") 614 | _add_doc(iterlists, 615 | "Return an iterator over the (key, [values]) pairs of a dictionary.") 616 | 617 | 618 | if PY3: 619 | def b(s): 620 | return s.encode("latin-1") 621 | 622 | def u(s): 623 | return s 624 | unichr = chr 625 | import struct 626 | int2byte = struct.Struct(">B").pack 627 | del struct 628 | byte2int = operator.itemgetter(0) 629 | indexbytes = operator.getitem 630 | iterbytes = iter 631 | import io 632 | StringIO = io.StringIO 633 | BytesIO = io.BytesIO 634 | _assertCountEqual = "assertCountEqual" 635 | if sys.version_info[1] <= 1: 636 | _assertRaisesRegex = "assertRaisesRegexp" 637 | _assertRegex = "assertRegexpMatches" 638 | else: 639 | _assertRaisesRegex = "assertRaisesRegex" 640 | _assertRegex = "assertRegex" 641 | else: 642 | def b(s): 643 | return s 644 | # Workaround for standalone backslash 645 | 646 | def u(s): 647 | return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") 648 | unichr = unichr 649 | int2byte = chr 650 | 651 | def byte2int(bs): 652 | return ord(bs[0]) 653 | 654 | def indexbytes(buf, i): 655 | return ord(buf[i]) 656 | iterbytes = functools.partial(itertools.imap, ord) 657 | import StringIO 658 | StringIO = BytesIO = StringIO.StringIO 659 | _assertCountEqual = "assertItemsEqual" 660 | _assertRaisesRegex = "assertRaisesRegexp" 661 | _assertRegex = "assertRegexpMatches" 662 | _add_doc(b, """Byte literal""") 663 | _add_doc(u, """Text literal""") 664 | 665 | 666 | def assertCountEqual(self, *args, **kwargs): 667 | return getattr(self, _assertCountEqual)(*args, **kwargs) 668 | 669 | 670 | def assertRaisesRegex(self, *args, **kwargs): 671 | return getattr(self, _assertRaisesRegex)(*args, **kwargs) 672 | 673 | 674 | def assertRegex(self, *args, **kwargs): 675 | return getattr(self, _assertRegex)(*args, **kwargs) 676 | 677 | 678 | if PY3: 679 | exec_ = getattr(moves.builtins, "exec") 680 | 681 | def reraise(tp, value, tb=None): 682 | if value is None: 683 | value = tp() 684 | if value.__traceback__ is not tb: 685 | raise value.with_traceback(tb) 686 | raise value 687 | 688 | else: 689 | def exec_(_code_, _globs_=None, _locs_=None): 690 | """Execute code in a namespace.""" 691 | if _globs_ is None: 692 | frame = sys._getframe(1) 693 | _globs_ = frame.f_globals 694 | if _locs_ is None: 695 | _locs_ = frame.f_locals 696 | del frame 697 | elif _locs_ is None: 698 | _locs_ = _globs_ 699 | exec("""exec _code_ in _globs_, _locs_""") 700 | 701 | exec_("""def reraise(tp, value, tb=None): 702 | raise tp, value, tb 703 | """) 704 | 705 | 706 | if sys.version_info[:2] == (3, 2): 707 | exec_("""def raise_from(value, from_value): 708 | if from_value is None: 709 | raise value 710 | raise value from from_value 711 | """) 712 | elif sys.version_info[:2] > (3, 2): 713 | exec_("""def raise_from(value, from_value): 714 | raise value from from_value 715 | """) 716 | else: 717 | def raise_from(value, from_value): 718 | raise value 719 | 720 | 721 | print_ = getattr(moves.builtins, "print", None) 722 | if print_ is None: 723 | def print_(*args, **kwargs): 724 | """The new-style print function for Python 2.4 and 2.5.""" 725 | fp = kwargs.pop("file", sys.stdout) 726 | if fp is None: 727 | return 728 | 729 | def write(data): 730 | if not isinstance(data, basestring): 731 | data = str(data) 732 | # If the file has an encoding, encode unicode with it. 733 | if (isinstance(fp, file) and 734 | isinstance(data, unicode) and 735 | fp.encoding is not None): 736 | errors = getattr(fp, "errors", None) 737 | if errors is None: 738 | errors = "strict" 739 | data = data.encode(fp.encoding, errors) 740 | fp.write(data) 741 | want_unicode = False 742 | sep = kwargs.pop("sep", None) 743 | if sep is not None: 744 | if isinstance(sep, unicode): 745 | want_unicode = True 746 | elif not isinstance(sep, str): 747 | raise TypeError("sep must be None or a string") 748 | end = kwargs.pop("end", None) 749 | if end is not None: 750 | if isinstance(end, unicode): 751 | want_unicode = True 752 | elif not isinstance(end, str): 753 | raise TypeError("end must be None or a string") 754 | if kwargs: 755 | raise TypeError("invalid keyword arguments to print()") 756 | if not want_unicode: 757 | for arg in args: 758 | if isinstance(arg, unicode): 759 | want_unicode = True 760 | break 761 | if want_unicode: 762 | newline = unicode("\n") 763 | space = unicode(" ") 764 | else: 765 | newline = "\n" 766 | space = " " 767 | if sep is None: 768 | sep = space 769 | if end is None: 770 | end = newline 771 | for i, arg in enumerate(args): 772 | if i: 773 | write(sep) 774 | write(arg) 775 | write(end) 776 | if sys.version_info[:2] < (3, 3): 777 | _print = print_ 778 | 779 | def print_(*args, **kwargs): 780 | fp = kwargs.get("file", sys.stdout) 781 | flush = kwargs.pop("flush", False) 782 | _print(*args, **kwargs) 783 | if flush and fp is not None: 784 | fp.flush() 785 | 786 | _add_doc(reraise, """Reraise an exception.""") 787 | 788 | if sys.version_info[0:2] < (3, 4): 789 | def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, 790 | updated=functools.WRAPPER_UPDATES): 791 | def wrapper(f): 792 | f = functools.wraps(wrapped, assigned, updated)(f) 793 | f.__wrapped__ = wrapped 794 | return f 795 | return wrapper 796 | else: 797 | wraps = functools.wraps 798 | 799 | 800 | def with_metaclass(meta, *bases): 801 | """Create a base class with a metaclass.""" 802 | # This requires a bit of explanation: the basic idea is to make a dummy 803 | # metaclass for one level of class instantiation that replaces itself with 804 | # the actual metaclass. 805 | class metaclass(meta): 806 | 807 | def __new__(cls, name, this_bases, d): 808 | return meta(name, bases, d) 809 | return type.__new__(metaclass, 'temporary_class', (), {}) 810 | 811 | 812 | def add_metaclass(metaclass): 813 | """Class decorator for creating a class with a metaclass.""" 814 | def wrapper(cls): 815 | orig_vars = cls.__dict__.copy() 816 | slots = orig_vars.get('__slots__') 817 | if slots is not None: 818 | if isinstance(slots, str): 819 | slots = [slots] 820 | for slots_var in slots: 821 | orig_vars.pop(slots_var) 822 | orig_vars.pop('__dict__', None) 823 | orig_vars.pop('__weakref__', None) 824 | return metaclass(cls.__name__, cls.__bases__, orig_vars) 825 | return wrapper 826 | 827 | 828 | def python_2_unicode_compatible(klass): 829 | """ 830 | A decorator that defines __unicode__ and __str__ methods under Python 2. 831 | Under Python 3 it does nothing. 832 | 833 | To support Python 2 and 3 with a single code base, define a __str__ method 834 | returning text and apply this decorator to the class. 835 | """ 836 | if PY2: 837 | if '__str__' not in klass.__dict__: 838 | raise ValueError("@python_2_unicode_compatible cannot be applied " 839 | "to %s because it doesn't define __str__()." % 840 | klass.__name__) 841 | klass.__unicode__ = klass.__str__ 842 | klass.__str__ = lambda self: self.__unicode__().encode('utf-8') 843 | return klass 844 | 845 | 846 | # Complete the moves implementation. 847 | # This code is at the end of this module to speed up module loading. 848 | # Turn this module into a package. 849 | __path__ = [] # required for PEP 302 and PEP 451 850 | __package__ = __name__ # see PEP 366 @ReservedAssignment 851 | if globals().get("__spec__") is not None: 852 | __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable 853 | # Remove other six meta path importers, since they cause problems. This can 854 | # happen if six is removed from sys.modules and then reloaded. (Setuptools does 855 | # this for some reason.) 856 | if sys.meta_path: 857 | for i, importer in enumerate(sys.meta_path): 858 | # Here's some real nastiness: Another "instance" of the six module might 859 | # be floating around. Therefore, we can't use isinstance() to check for 860 | # the six meta path importer, since the other six instance will have 861 | # inserted an importer with different class. 862 | if (type(importer).__name__ == "_SixMetaPathImporter" and 863 | importer.name == __name__): 864 | del sys.meta_path[i] 865 | break 866 | del i, importer 867 | # Finally, add the importer to the meta path import hook. 868 | sys.meta_path.append(_importer) 869 | --------------------------------------------------------------------------------