__negotiatesocks5(self,destaddr,destport) Negotiates a connection through a SOCKS5 server.
(self, destaddr, destport)
| 169 | self.__proxy = (proxytype, addr, port, rdns, username, password) |
| 170 | |
| 171 | def __negotiatesocks5(self, destaddr, destport): |
| 172 | """__negotiatesocks5(self,destaddr,destport) |
| 173 | Negotiates a connection through a SOCKS5 server. |
| 174 | """ |
| 175 | # First we'll send the authentication packages we support. |
| 176 | if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): |
| 177 | # The username/password details were supplied to the |
| 178 | # setproxy method so we support the USERNAME/PASSWORD |
| 179 | # authentication (in addition to the standard none). |
| 180 | self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) |
| 181 | else: |
| 182 | # No username/password were entered, therefore we |
| 183 | # only support connections with no authentication. |
| 184 | self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) |
| 185 | # We'll receive the server's response to determine which |
| 186 | # method was selected |
| 187 | chosenauth = self.__recvall(2) |
| 188 | if chosenauth[0:1] != b'\x05': |
| 189 | self.close() |
| 190 | raise GeneralProxyError((1, _generalerrors[1])) |
| 191 | # Check the chosen authentication method |
| 192 | if chosenauth[1:2] == b'\x00': |
| 193 | # No authentication is required |
| 194 | pass |
| 195 | elif chosenauth[1:2] == b'\x02': |
| 196 | # Okay, we need to perform a basic username/password |
| 197 | # authentication. |
| 198 | self.sendall(b'\x01' + chr(len(self.__proxy[4])).encode() + self.__proxy[4].encode() + chr(len(self.__proxy[5])).encode() + self.__proxy[5].encode()) |
| 199 | authstat = self.__recvall(2) |
| 200 | if authstat[0:1] != b'\x01': |
| 201 | # Bad response |
| 202 | self.close() |
| 203 | raise GeneralProxyError((1, _generalerrors[1])) |
| 204 | if authstat[1:2] != b'\x00': |
| 205 | # Authentication failed |
| 206 | self.close() |
| 207 | raise Socks5AuthError((3, _socks5autherrors[3])) |
| 208 | # Authentication succeeded |
| 209 | else: |
| 210 | # Reaching here is always bad |
| 211 | self.close() |
| 212 | if chosenauth[1:2] == b'\xff': |
| 213 | raise Socks5AuthError((2, _socks5autherrors[2])) |
| 214 | else: |
| 215 | raise GeneralProxyError((1, _generalerrors[1])) |
| 216 | # Now we can request the actual connection |
| 217 | req = struct.pack('BBB', 0x05, 0x01, 0x00) |
| 218 | # If the given destination address is an IP address, we'll |
| 219 | # use the IPv4 address request even if remote resolving was specified. |
| 220 | try: |
| 221 | ipaddr = socket.inet_aton(destaddr) |
| 222 | req = req + b'\x01' + ipaddr |
| 223 | except socket.error: |
| 224 | # Well it's not an IP number, so it's probably a DNS name. |
| 225 | if self.__proxy[3]: |
| 226 | # Resolve remotely |
| 227 | ipaddr = None |
| 228 | req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + (destaddr if isinstance(destaddr, bytes) else destaddr.encode()) |
no test coverage detected