Handle socks5 request according to RFC1928.
(self)
| 137 | self.handler_index = None |
| 138 | |
| 139 | def handle(self): |
| 140 | """Handle socks5 request according to RFC1928.""" |
| 141 | log_exception_prefix = "Socks5Connection.handle(): " |
| 142 | try: |
| 143 | log_exception_prefix = ("Socks5Connection.handle(" |
| 144 | f"client={format_sock(self.conn, local=False)}, " |
| 145 | f"proxy={format_sock(self.conn, local=True)}): ") |
| 146 | |
| 147 | # Verify socks version |
| 148 | ver = recvall(self.conn, 1)[0] |
| 149 | if ver != 0x05: |
| 150 | raise IOError('Invalid socks version %i' % ver) |
| 151 | # Choose authentication method |
| 152 | nmethods = recvall(self.conn, 1)[0] |
| 153 | methods = bytearray(recvall(self.conn, nmethods)) |
| 154 | method = None |
| 155 | if 0x02 in methods and self.serv.conf.auth: |
| 156 | method = 0x02 # username/password |
| 157 | elif 0x00 in methods and self.serv.conf.unauth: |
| 158 | method = 0x00 # unauthenticated |
| 159 | if method is None: |
| 160 | raise IOError('No supported authentication method was offered') |
| 161 | # Send response |
| 162 | self.conn.sendall(bytearray([0x05, method])) |
| 163 | # Read authentication (optional) |
| 164 | username = None |
| 165 | password = None |
| 166 | if method == 0x02: |
| 167 | ver = recvall(self.conn, 1)[0] |
| 168 | if ver != 0x01: |
| 169 | raise IOError('Invalid auth packet version %i' % ver) |
| 170 | ulen = recvall(self.conn, 1)[0] |
| 171 | username = str(recvall(self.conn, ulen)) |
| 172 | plen = recvall(self.conn, 1)[0] |
| 173 | password = str(recvall(self.conn, plen)) |
| 174 | # Send authentication response |
| 175 | self.conn.sendall(bytearray([0x01, 0x00])) |
| 176 | |
| 177 | # Read connect request |
| 178 | ver, cmd, _, atyp = recvall(self.conn, 4) |
| 179 | if ver != 0x05: |
| 180 | raise IOError('Invalid socks version %i in connect request' % ver) |
| 181 | if cmd != Command.CONNECT: |
| 182 | raise IOError('Unhandled command %i in connect request' % cmd) |
| 183 | |
| 184 | if atyp == AddressType.IPV4: |
| 185 | addr = recvall(self.conn, 4) |
| 186 | elif atyp == AddressType.DOMAINNAME: |
| 187 | n = recvall(self.conn, 1)[0] |
| 188 | addr = recvall(self.conn, n) |
| 189 | elif atyp == AddressType.IPV6: |
| 190 | addr = recvall(self.conn, 16) |
| 191 | else: |
| 192 | raise IOError('Unknown address type %i' % atyp) |
| 193 | port_hi,port_lo = recvall(self.conn, 2) |
| 194 | port = (port_hi << 8) | port_lo |
| 195 | |
| 196 | # Send dummy response |
nothing calls this directly
no test coverage detected