diff options
Diffstat (limited to 'python2')
| -rw-r--r-- | python2/httplib2/socks.py | 180 |
1 files changed, 96 insertions, 84 deletions
diff --git a/python2/httplib2/socks.py b/python2/httplib2/socks.py index bbbf9a0..2bddd7a 100644 --- a/python2/httplib2/socks.py +++ b/python2/httplib2/socks.py @@ -3,8 +3,8 @@ Version 1.00 Copyright 2006 Dan-Haim. All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, @@ -22,7 +22,7 @@ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This module provides a standard socket-like interface for Python @@ -49,11 +49,10 @@ PROXY_TYPE_SOCKS5 = 2 PROXY_TYPE_HTTP = 3 _defaultproxy = None -_orgsocket = socket.socket # Small hack for Python 2.x if sys.version_info[0] <= 2: - def bytes(obj, enc = None): + def bytes(obj, enc=None): return obj class ProxyError(Exception): @@ -93,42 +92,47 @@ class HTTPError(ProxyError): return repr(self.value) _generalerrors = ("success", - "invalid data", - "not connected", - "not available", - "bad proxy type", - "bad input") + "invalid data", + "not connected", + "not available", + "bad proxy type", + "bad input") _socks5errors = ("succeeded", - "general SOCKS server failure", - "connection not allowed by ruleset", - "Network unreachable", - "Host unreachable", - "Connection refused", - "TTL expired", - "Command not supported", - "Address type not supported", - "Unknown error") + "general SOCKS server failure", + "connection not allowed by ruleset", + "Network unreachable", + "Host unreachable", + "Connection refused", + "TTL expired", + "Command not supported", + "Address type not supported", + "Unknown error") _socks5autherrors = ("succeeded", - "authentication is required", - "all offered authentication methods were rejected", - "unknown username or invalid password", - "unknown error") + "authentication is required", + "all offered authentication methods were rejected", + "unknown username or invalid password", + "unknown error") _socks4errors = ("request granted", - "request rejected or failed", - "request rejected because SOCKS server cannot connect to identd on the client", - "request rejected because the client program and identd report different user-ids", - "unknown error") + "request rejected or failed", + ("request rejected because SOCKS server cannot connect to " + "identd on the client"), + ("request rejected because the client program and identd" + " report different user-ids"), + "unknown error") -def setdefaultproxy(proxytype=None,addr=None,port=None,rdns=True,username=None,password=None): + +def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, + username=None, password=None): """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) Sets a default proxy which all further socksocket objects will use, unless explicitly changed. """ global _defaultproxy - _defaultproxy = (proxytype,addr,port,rdns,username,password) + _defaultproxy = (proxytype, addr, port, rdns, username, password) + class socksocket(socket.socket): """socksocket([family[, type[, proto]]]) -> socket object @@ -138,8 +142,9 @@ class socksocket(socket.socket): you must specify family=AF_INET, type=SOCK_STREAM and proto=0. """ - def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): - _orgsocket.__init__(self,family,type,proto,_sock) + def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=0, _sock=None): + socket.socket.__init__(self, family, type, proto, _sock) if _defaultproxy != None: self.__proxy = _defaultproxy else: @@ -148,7 +153,7 @@ class socksocket(socket.socket): self.__proxypeername = None def __decode(self, bytes): - if 'decode' in dir(bytes): + if getattr(bytes, 'decode', False): try: bytes = bytes.decode() except Exception: @@ -156,7 +161,7 @@ class socksocket(socket.socket): return bytes def __encode(self, bytes): - if 'encode' in dir(bytes): + if getattr(bytes, 'encode', False): try: bytes = bytes.encode() except Exception: @@ -170,15 +175,18 @@ class socksocket(socket.socket): """ data = bytes("") while len(data) < count: - d = self.recv(count-len(data)) - if not d: raise GeneralProxyError((0,"connection closed unexpectedly")) + d = self.recv(count - len(data)) + if not d: + raise GeneralProxyError( + (0, "connection closed unexpectedly")) data = data + self.__decode(d) return data def sendall(self, bytes): socket.socket.sendall(self, self.__encode(bytes)) - def setproxy(self,proxytype=None,addr=None,port=None,rdns=True,username=None,password=None): + def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, + username=None, password=None): """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) Sets the proxy to be used. proxytype - The type of the proxy to be used. Three types @@ -195,14 +203,14 @@ class socksocket(socket.socket): password - Password to authenticate with to the server. Only relevant when username is also provided. """ - self.__proxy = (proxytype,addr,port,rdns,username,password) + self.__proxy = (proxytype, addr, port, rdns, username, password) - def __negotiatesocks5(self,destaddr,destport): + def __negotiatesocks5(self, destaddr, destport): """__negotiatesocks5(self,destaddr,destport) Negotiates a connection through a SOCKS5 server. """ # First we'll send the authentication packages we support. - if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): + if (self.__proxy[4] != None) and (self.__proxy[5] != None): # The username/password details were supplied to the # setproxy method so we support the USERNAME/PASSWORD # authentication (in addition to the standard none). @@ -216,7 +224,7 @@ class socksocket(socket.socket): chosenauth = self.__recvall(2) if chosenauth[0] != "\x05": self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) # Check the chosen authentication method if chosenauth[1] == "\x00": # No authentication is required @@ -224,24 +232,25 @@ class socksocket(socket.socket): elif chosenauth[1] == "\x02": # Okay, we need to perform a basic username/password # authentication. - self.sendall("\x01" + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) + self.sendall("\x01" + chr(len(self.__proxy[4])) + self.__proxy[4] + + chr(len(self.__proxy[5])) + self.__proxy[5]) authstat = self.__recvall(2) if authstat[0] != "\x01": # Bad response self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) if authstat[1] != "\x00": # Authentication failed self.close() - raise Socks5AuthError((3,_socks5autherrors[3])) + raise Socks5AuthError((3, _socks5autherrors[3])) # Authentication succeeded else: # Reaching here is always bad self.close() if chosenauth[1] == "\xFF": - raise Socks5AuthError((2,_socks5autherrors[2])) + raise Socks5AuthError((2, _socks5autherrors[2])) else: - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) # Now we can request the actual connection req = "\x05\x01\x00" # If the given destination address is an IP address, we'll @@ -251,7 +260,7 @@ class socksocket(socket.socket): req = req + "\x01" + ipaddr except socket.error: # Well it's not an IP number, so it's probably a DNS name. - if self.__proxy[3]==True: + if self.__proxy[3] == True: # Resolve remotely ipaddr = None req = req + "\x03" + chr(len(destaddr)) + destaddr @@ -259,20 +268,20 @@ class socksocket(socket.socket): # Resolve locally ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) req = req + "\x01" + ipaddr - req = req + self.__decode(struct.pack(">H",destport)) + req = req + self.__decode(struct.pack(">H", destport)) self.sendall(req) # Get the response resp = self.__recvall(4) if resp[0] != "\x05": self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) elif resp[1] != "\x00": # Connection failed self.close() - if ord(resp[1])<=8: - raise Socks5Error((ord(resp[1]),_socks5errors[ord(resp[1])])) + if ord(resp[1]) <= 8: + raise Socks5Error((ord(resp[1]), _socks5errors[ord(resp[1])])) else: - raise Socks5Error((9,_socks5errors[9])) + raise Socks5Error((9, _socks5errors[9])) # Get the bound address/port elif resp[3] == "\x01": boundaddr = self.__recvall(4) @@ -281,13 +290,13 @@ class socksocket(socket.socket): boundaddr = self.__recvall(ord(resp[4])) else: self.close() - raise GeneralProxyError((1,_generalerrors[1])) - boundport = struct.unpack(">H",bytes(self.__recvall(2), 'utf8'))[0] - self.__proxysockname = (boundaddr,boundport) + raise GeneralProxyError((1, _generalerrors[1])) + boundport = struct.unpack(">H", bytes(self.__recvall(2), 'utf8'))[0] + self.__proxysockname = boundaddr, boundport if ipaddr != None: - self.__proxypeername = (socket.inet_ntoa(ipaddr),destport) + self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) else: - self.__proxypeername = (destaddr,destport) + self.__proxypeername = (destaddr, destport) def getproxysockname(self): """getsockname() -> address info @@ -299,7 +308,7 @@ class socksocket(socket.socket): """getproxypeername() -> address info Returns the IP and port number of the proxy. """ - return _orgsocket.getpeername(self) + return socket.socket.getpeername(self) def getpeername(self): """getpeername() -> address info @@ -308,7 +317,7 @@ class socksocket(socket.socket): """ return self.__proxypeername - def __negotiatesocks4(self,destaddr,destport): + def __negotiatesocks4(self, destaddr, destport): """__negotiatesocks4(self,destaddr,destport) Negotiates a connection through a SOCKS4 server. """ @@ -318,13 +327,13 @@ class socksocket(socket.socket): ipaddr = socket.inet_aton(destaddr) except socket.error: # It's a DNS name. Check where it should be resolved. - if self.__proxy[3]==True: + if self.__proxy[3] == True: ipaddr = "\x00\x00\x00\x01" rmtrslv = True else: ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) # Construct the request packet - req = "\x04\x01" + self.__decode(struct.pack(">H",destport)) + ipaddr + req = "\x04\x01" + self.__decode(struct.pack(">H", destport)) + ipaddr # The username parameter is considered userid for SOCKS4 if self.__proxy[4] != None: req = req + self.__proxy[4] @@ -340,13 +349,13 @@ class socksocket(socket.socket): if resp[0] != "\x00": # Bad data self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) if resp[1] != "\x5A": # Server returned an error self.close() if ord(resp[1]) in (91,92,93): self.close() - raise Socks4Error((ord(resp[1]),_socks4errors[ord(resp[1])-90])) + raise Socks4Error((ord(resp[1]), _socks4errors[ord(resp[1])-90])) else: raise Socks4Error((94,_socks4errors[4])) # Get the bound address/port @@ -354,9 +363,9 @@ class socksocket(socket.socket): if rmtrslv != None: self.__proxypeername = (socket.inet_ntoa(ipaddr),destport) else: - self.__proxypeername = (destaddr,destport) + self.__proxypeername = (destaddr, destport) - def __negotiatehttp(self,destaddr,destport): + def __negotiatehttp(self, destaddr, destport): """__negotiatehttp(self,destaddr,destport) Negotiates a connection through an HTTP server. """ @@ -365,29 +374,30 @@ class socksocket(socket.socket): addr = socket.gethostbyname(destaddr) else: addr = destaddr - self.sendall("CONNECT " + addr + ":" + str(destport) + " HTTP/1.1\r\n" + "Host: " + destaddr + "\r\n\r\n") + self.sendall(("CONNECT %s:%s HTTP/1.1\r\n" + "Host: %s\r\n\r\n") % (addr, destport, destaddr)) # We read the response until we get the string "\r\n\r\n" resp = self.recv(1) - while resp.find("\r\n\r\n")==-1: + while resp.find("\r\n\r\n") == -1: resp = resp + self.recv(1) # We just need the first line to check if the connection # was successful - statusline = resp.splitlines()[0].split(" ",2) - if statusline[0] not in ("HTTP/1.0","HTTP/1.1"): + statusline = resp.splitlines()[0].split(" ", 2) + if statusline[0] not in ("HTTP/1.0", "HTTP/1.1"): self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) try: statuscode = int(statusline[1]) except ValueError: self.close() - raise GeneralProxyError((1,_generalerrors[1])) + raise GeneralProxyError((1, _generalerrors[1])) if statuscode != 200: self.close() - raise HTTPError((statuscode,statusline[2])) - self.__proxysockname = ("0.0.0.0",0) - self.__proxypeername = (addr,destport) + raise HTTPError((statuscode, statusline[2])) + self.__proxysockname = ("0.0.0.0", 0) + self.__proxypeername = (addr, destport) - def connect(self,destpair): + def connect(self, destpair): """connect(self,despair) Connects to the specified destination through a proxy. destpar - A tuple of the IP/DNS address and the port number. @@ -395,30 +405,32 @@ class socksocket(socket.socket): To select the proxy server use setproxy(). """ # Do a minimal input check first - if (type(destpair) in (list,tuple)==False) or (len(destpair)<2) or (type(destpair[0])!=str) or (type(destpair[1])!=int): - raise GeneralProxyError((5,_generalerrors[5])) + # TODO(durin42): seriously? type checking? do we care? + if ((not isinstance(destpair, (list, tuple))) or len(destpair) < 2 + or not isinstance(destpair[0], str) or not isinstance(destpair[1], int)): + raise GeneralProxyError((5, _generalerrors[5])) if self.__proxy[0] == PROXY_TYPE_SOCKS5: if self.__proxy[2] != None: portnum = self.__proxy[2] else: portnum = 1080 - _orgsocket.connect(self,(self.__proxy[1],portnum)) - self.__negotiatesocks5(destpair[0],destpair[1]) + socket.socket.connect(self,(self.__proxy[1], portnum)) + self.__negotiatesocks5(destpair[0], destpair[1]) elif self.__proxy[0] == PROXY_TYPE_SOCKS4: if self.__proxy[2] != None: portnum = self.__proxy[2] else: portnum = 1080 - _orgsocket.connect(self,(self.__proxy[1],portnum)) - self.__negotiatesocks4(destpair[0],destpair[1]) + socket.socket.connect(self, (self.__proxy[1], portnum)) + self.__negotiatesocks4(destpair[0], destpair[1]) elif self.__proxy[0] == PROXY_TYPE_HTTP: if self.__proxy[2] != None: portnum = self.__proxy[2] else: portnum = 8080 - _orgsocket.connect(self,(self.__proxy[1],portnum)) - self.__negotiatehttp(destpair[0],destpair[1]) + socket.socket.connect(self, (self.__proxy[1], portnum)) + self.__negotiatehttp(destpair[0], destpair[1]) elif self.__proxy[0] == None: - _orgsocket.connect(self,(destpair[0],destpair[1])) + socket.socket.connect(self, (destpair[0], destpair[1])) else: - raise GeneralProxyError((4,_generalerrors[4])) + raise GeneralProxyError((4, _generalerrors[4])) |
