An attempt at adding UDP support to aiosocks. Untested due to lack of server support.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

691 lines
22 KiB

  1. import asyncio
  2. import aiosocks
  3. import pytest
  4. import socket
  5. import ssl as ssllib
  6. from unittest import mock
  7. from asyncio import coroutine as coro, sslproto
  8. from aiohttp.test_utils import make_mocked_coro
  9. import aiosocks.constants as c
  10. from aiosocks.protocols import BaseSocksProtocol
  11. from aiosocks.errors import InvalidServerReply
  12. def make_base(loop, *, dst=None, waiter=None, ap_factory=None, ssl=None):
  13. dst = dst or ('python.org', 80)
  14. proto = BaseSocksProtocol(None, None, dst=dst, ssl=ssl,
  15. loop=loop, waiter=waiter,
  16. app_protocol_factory=ap_factory)
  17. return proto
  18. def make_socks4(loop, *, addr=None, auth=None, rr=True, dst=None, r=b'',
  19. ap_factory=None, whiter=None):
  20. addr = addr or aiosocks.Socks4Addr('localhost', 1080)
  21. auth = auth or aiosocks.Socks4Auth('user')
  22. dst = dst or ('python.org', 80)
  23. proto = aiosocks.Socks4Protocol(
  24. proxy=addr, proxy_auth=auth, dst=dst, remote_resolve=rr,
  25. loop=loop, app_protocol_factory=ap_factory, waiter=whiter)
  26. proto._stream_writer = mock.Mock()
  27. proto.read_response = mock.Mock(
  28. side_effect=coro(mock.Mock(return_value=r)))
  29. proto._get_dst_addr = mock.Mock(
  30. side_effect=coro(mock.Mock(return_value=(socket.AF_INET, '127.0.0.1')))
  31. )
  32. return proto
  33. def make_socks5(loop, *, addr=None, auth=None, rr=True, dst=None, r=None,
  34. ap_factory=None, whiter=None, user='user', pwd='pwd'):
  35. addr = addr or aiosocks.Socks5Addr('localhost', 1080)
  36. auth = auth or aiosocks.Socks5Auth(user, pwd)
  37. dst = dst or ('python.org', 80)
  38. proto = aiosocks.Socks5Protocol(
  39. proxy=addr, proxy_auth=auth, dst=dst, remote_resolve=rr,
  40. loop=loop, app_protocol_factory=ap_factory, waiter=whiter)
  41. proto._stream_writer = mock.Mock()
  42. proto._stream_writer.drain = make_mocked_coro(True)
  43. if not isinstance(r, (list, tuple)):
  44. proto.read_response = mock.Mock(
  45. side_effect=coro(mock.Mock(return_value=r)))
  46. else:
  47. proto.read_response = mock.Mock(
  48. side_effect=coro(mock.Mock(side_effect=r)))
  49. proto._get_dst_addr = mock.Mock(
  50. side_effect=coro(mock.Mock(return_value=(socket.AF_INET, '127.0.0.1')))
  51. )
  52. return proto
  53. def test_base_ctor(loop):
  54. with pytest.raises(ValueError):
  55. BaseSocksProtocol(None, None, None, loop=loop,
  56. waiter=None, app_protocol_factory=None)
  57. with pytest.raises(ValueError):
  58. BaseSocksProtocol(None, None, 123, loop=loop,
  59. waiter=None, app_protocol_factory=None)
  60. with pytest.raises(ValueError):
  61. BaseSocksProtocol(None, None, ('python.org',), loop=loop,
  62. waiter=None, app_protocol_factory=None)
  63. def test_base_write_request(loop):
  64. proto = make_base(loop)
  65. proto._stream_writer = mock.Mock()
  66. proto.write_request([b'\x00', b'\x01\x02', 0x03])
  67. proto._stream_writer.write.assert_called_with(b'\x00\x01\x02\x03')
  68. with pytest.raises(ValueError):
  69. proto.write_request(['\x00'])
  70. async def test_base_negotiate_os_error(loop):
  71. waiter = asyncio.Future(loop=loop)
  72. proto = make_base(loop, waiter=waiter)
  73. proto.socks_request = make_mocked_coro(raise_exception=OSError('test'))
  74. await proto.negotiate(None, None)
  75. with pytest.raises(OSError) as ct:
  76. await waiter
  77. assert 'test' in str(ct)
  78. async def test_base_negotiate_socks_err(loop):
  79. waiter = asyncio.Future(loop=loop)
  80. proto = make_base(loop, waiter=waiter)
  81. proto.socks_request = make_mocked_coro(
  82. raise_exception=aiosocks.SocksError('test'))
  83. await proto.negotiate(None, None)
  84. with pytest.raises(aiosocks.SocksError) as ct:
  85. await waiter
  86. assert 'Can not connect to' in str(ct)
  87. async def test_base_negotiate_without_app_proto(loop):
  88. waiter = asyncio.Future(loop=loop)
  89. proto = make_base(loop, waiter=waiter)
  90. proto.socks_request = make_mocked_coro((None, None))
  91. proto._transport = True
  92. await proto.negotiate(None, None)
  93. await waiter
  94. assert waiter.done()
  95. async def test_base_negotiate_with_app_proto(loop):
  96. waiter = asyncio.Future(loop=loop)
  97. proto = make_base(loop, waiter=waiter,
  98. ap_factory=lambda: asyncio.Protocol())
  99. proto.socks_request = make_mocked_coro((None, None))
  100. await proto.negotiate(None, None)
  101. await waiter
  102. assert waiter.done()
  103. def test_base_connection_lost():
  104. loop_mock = mock.Mock()
  105. app_proto = mock.Mock()
  106. proto = make_base(loop_mock, ap_factory=lambda: app_proto)
  107. # negotiate not completed
  108. proto._negotiate_done = False
  109. proto.connection_lost(True)
  110. assert not loop_mock.call_soon.called
  111. # negotiate successfully competed
  112. loop_mock.reset_mock()
  113. proto._negotiate_done = True
  114. proto.connection_lost(True)
  115. assert loop_mock.call_soon.called
  116. # don't call connect_lost, if app_protocol == self
  117. # otherwise recursion
  118. loop_mock.reset_mock()
  119. proto = make_base(loop_mock, ap_factory=None)
  120. proto._negotiate_done = True
  121. proto.connection_lost(True)
  122. assert not loop_mock.call_soon.called
  123. def test_base_pause_writing():
  124. loop_mock = mock.Mock()
  125. app_proto = mock.Mock()
  126. proto = make_base(loop_mock, ap_factory=lambda: app_proto)
  127. # negotiate not completed
  128. proto._negotiate_done = False
  129. proto.pause_writing()
  130. assert not proto._app_protocol.pause_writing.called
  131. # negotiate successfully competed
  132. app_proto.reset_mock()
  133. proto._negotiate_done = True
  134. proto.pause_writing()
  135. assert proto._app_protocol.pause_writing.called
  136. # don't call pause_writing, if app_protocol == self
  137. # otherwise recursion
  138. app_proto.reset_mock()
  139. proto = make_base(loop_mock)
  140. proto._negotiate_done = True
  141. proto.pause_writing()
  142. def test_base_resume_writing():
  143. loop_mock = mock.Mock()
  144. app_proto = mock.Mock()
  145. proto = make_base(loop_mock, ap_factory=lambda: app_proto)
  146. # negotiate not completed
  147. proto._negotiate_done = False
  148. # negotiate not completed
  149. with pytest.raises(AssertionError):
  150. proto.resume_writing()
  151. assert not proto._app_protocol.resume_writing.called
  152. # negotiate successfully competed
  153. loop_mock.reset_mock()
  154. proto._negotiate_done = True
  155. proto.resume_writing()
  156. assert proto._app_protocol.resume_writing.called
  157. # don't call resume_writing, if app_protocol == self
  158. # otherwise recursion
  159. loop_mock.reset_mock()
  160. proto = make_base(loop_mock)
  161. proto._negotiate_done = True
  162. with pytest.raises(AssertionError):
  163. proto.resume_writing()
  164. def test_base_data_received():
  165. loop_mock = mock.Mock()
  166. app_proto = mock.Mock()
  167. proto = make_base(loop_mock, ap_factory=lambda: app_proto)
  168. # negotiate not completed
  169. proto._negotiate_done = False
  170. proto.data_received(b'123')
  171. assert not proto._app_protocol.data_received.called
  172. # negotiate successfully competed
  173. app_proto.reset_mock()
  174. proto._negotiate_done = True
  175. proto.data_received(b'123')
  176. assert proto._app_protocol.data_received.called
  177. # don't call data_received, if app_protocol == self
  178. # otherwise recursion
  179. loop_mock.reset_mock()
  180. proto = make_base(loop_mock)
  181. proto._negotiate_done = True
  182. proto.data_received(b'123')
  183. def test_base_eof_received():
  184. loop_mock = mock.Mock()
  185. app_proto = mock.Mock()
  186. proto = make_base(loop_mock, ap_factory=lambda: app_proto)
  187. # negotiate not completed
  188. proto._negotiate_done = False
  189. proto.eof_received()
  190. assert not proto._app_protocol.eof_received.called
  191. # negotiate successfully competed
  192. app_proto.reset_mock()
  193. proto._negotiate_done = True
  194. proto.eof_received()
  195. assert proto._app_protocol.eof_received.called
  196. # don't call pause_writing, if app_protocol == self
  197. # otherwise recursion
  198. app_proto.reset_mock()
  199. proto = make_base(loop_mock)
  200. proto._negotiate_done = True
  201. proto.eof_received()
  202. async def test_base_make_ssl_proto():
  203. loop_mock = mock.Mock()
  204. app_proto = mock.Mock()
  205. ssl_context = ssllib.create_default_context()
  206. proto = make_base(loop_mock,
  207. ap_factory=lambda: app_proto, ssl=ssl_context)
  208. proto.socks_request = make_mocked_coro((None, None))
  209. proto._transport = mock.Mock()
  210. await proto.negotiate(None, None)
  211. assert isinstance(proto._transport, sslproto._SSLProtocolTransport)
  212. async def test_base_func_negotiate_cb_call():
  213. loop_mock = mock.Mock()
  214. waiter = mock.Mock()
  215. proto = make_base(loop_mock, waiter=waiter)
  216. proto.socks_request = make_mocked_coro((None, None))
  217. proto._negotiate_done_cb = mock.Mock()
  218. with mock.patch('aiosocks.protocols.asyncio.Task') as task_mock:
  219. await proto.negotiate(None, None)
  220. assert proto._negotiate_done_cb.called
  221. assert not task_mock.called
  222. async def test_base_coro_negotiate_cb_call():
  223. loop_mock = mock.Mock()
  224. waiter = mock.Mock()
  225. proto = make_base(loop_mock, waiter=waiter)
  226. proto.socks_request = make_mocked_coro((None, None))
  227. proto._negotiate_done_cb = make_mocked_coro(None)
  228. with mock.patch('aiosocks.protocols.asyncio.Task') as task_mock:
  229. await proto.negotiate(None, None)
  230. assert proto._negotiate_done_cb.called
  231. assert task_mock.called
  232. async def test_base_reader_limit(loop):
  233. proto = BaseSocksProtocol(None, None, ('python.org', 80),
  234. None, None, reader_limit=10, loop=loop)
  235. assert proto.reader._limit == 10
  236. proto = BaseSocksProtocol(None, None, ('python.org', 80),
  237. None, None, reader_limit=15, loop=loop)
  238. assert proto.reader._limit == 15
  239. async def test_base_incomplete_error(loop):
  240. proto = BaseSocksProtocol(None, None, ('python.org', 80),
  241. None, None, reader_limit=10, loop=loop)
  242. proto._stream_reader.readexactly = make_mocked_coro(
  243. raise_exception=asyncio.IncompleteReadError(b'part', 5))
  244. with pytest.raises(aiosocks.InvalidServerReply):
  245. await proto.read_response(4)
  246. def test_socks4_ctor(loop):
  247. addr = aiosocks.Socks4Addr('localhost', 1080)
  248. auth = aiosocks.Socks4Auth('user')
  249. dst = ('python.org', 80)
  250. with pytest.raises(ValueError):
  251. aiosocks.Socks4Protocol(None, None, dst, loop=loop,
  252. waiter=None, app_protocol_factory=None)
  253. with pytest.raises(ValueError):
  254. aiosocks.Socks4Protocol(None, auth, dst, loop=loop,
  255. waiter=None, app_protocol_factory=None)
  256. with pytest.raises(ValueError):
  257. aiosocks.Socks4Protocol(aiosocks.Socks5Addr('host'), auth, dst,
  258. loop=loop, waiter=None,
  259. app_protocol_factory=None)
  260. with pytest.raises(ValueError):
  261. aiosocks.Socks4Protocol(addr, aiosocks.Socks5Auth('l', 'p'), dst,
  262. loop=loop, waiter=None,
  263. app_protocol_factory=None)
  264. aiosocks.Socks4Protocol(addr, None, dst, loop=loop,
  265. waiter=None, app_protocol_factory=None)
  266. aiosocks.Socks4Protocol(addr, auth, dst, loop=loop,
  267. waiter=None, app_protocol_factory=None)
  268. async def test_socks4_dst_domain_with_remote_resolve(loop):
  269. proto = make_socks4(loop, dst=('python.org', 80),
  270. r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  271. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  272. proto._stream_writer.write.assert_called_with(
  273. b'\x04\x01\x00P\x00\x00\x00\x01user\x00python.org\x00')
  274. async def test_socks4_dst_domain_with_local_resolve(loop):
  275. proto = make_socks4(loop, dst=('python.org', 80),
  276. rr=False, r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  277. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  278. proto._stream_writer.write.assert_called_with(
  279. b'\x04\x01\x00P\x7f\x00\x00\x01user\x00')
  280. async def test_socks4_dst_ip_with_remote_resolve(loop):
  281. proto = make_socks4(loop, dst=('127.0.0.1', 8800),
  282. r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  283. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  284. proto._stream_writer.write.assert_called_with(
  285. b'\x04\x01"`\x7f\x00\x00\x01user\x00')
  286. async def test_socks4_dst_ip_with_locale_resolve(loop):
  287. proto = make_socks4(loop, dst=('127.0.0.1', 8800),
  288. rr=False, r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  289. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  290. proto._stream_writer.write.assert_called_with(
  291. b'\x04\x01"`\x7f\x00\x00\x01user\x00')
  292. async def test_socks4_dst_domain_without_user(loop):
  293. proto = make_socks4(loop, auth=aiosocks.Socks4Auth(''),
  294. dst=('python.org', 80),
  295. r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  296. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  297. proto._stream_writer.write.assert_called_with(
  298. b'\x04\x01\x00P\x00\x00\x00\x01\x00python.org\x00')
  299. async def test_socks4_dst_ip_without_user(loop):
  300. proto = make_socks4(loop, auth=aiosocks.Socks4Auth(''),
  301. dst=('127.0.0.1', 8800),
  302. r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  303. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  304. proto._stream_writer.write.assert_called_with(
  305. b'\x04\x01"`\x7f\x00\x00\x01\x00')
  306. async def test_socks4_valid_resp_handling(loop):
  307. proto = make_socks4(loop, r=b'\x00\x5a\x00P\x7f\x00\x00\x01')
  308. r = await proto.socks_request(c.SOCKS_CMD_CONNECT)
  309. assert r == (('python.org', 80), ('127.0.0.1', 80))
  310. async def test_socks4_invalid_reply_resp_handling(loop):
  311. proto = make_socks4(loop, r=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF')
  312. with pytest.raises(aiosocks.InvalidServerReply):
  313. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  314. async def test_socks_err_resp_handling(loop):
  315. proto = make_socks4(loop, r=b'\x00\x5b\x00P\x7f\x00\x00\x01')
  316. with pytest.raises(aiosocks.SocksError) as cm:
  317. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  318. assert '0x5b' in str(cm)
  319. async def test_socks4_unknown_err_resp_handling(loop):
  320. proto = make_socks4(loop, r=b'\x00\x5e\x00P\x7f\x00\x00\x01')
  321. with pytest.raises(aiosocks.SocksError) as cm:
  322. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  323. assert 'Unknown error' in str(cm)
  324. def test_socks5_ctor(loop):
  325. addr = aiosocks.Socks5Addr('localhost', 1080)
  326. auth = aiosocks.Socks5Auth('user', 'pwd')
  327. dst = ('python.org', 80)
  328. with pytest.raises(ValueError):
  329. aiosocks.Socks5Protocol(None, None, dst, loop=loop,
  330. waiter=None, app_protocol_factory=None)
  331. with pytest.raises(ValueError):
  332. aiosocks.Socks5Protocol(None, auth, dst, loop=loop,
  333. waiter=None, app_protocol_factory=None)
  334. with pytest.raises(ValueError):
  335. aiosocks.Socks5Protocol(aiosocks.Socks4Addr('host'),
  336. auth, dst, loop=loop,
  337. waiter=None, app_protocol_factory=None)
  338. with pytest.raises(ValueError):
  339. aiosocks.Socks5Protocol(addr, aiosocks.Socks4Auth('l'),
  340. dst, loop=loop,
  341. waiter=None, app_protocol_factory=None)
  342. aiosocks.Socks5Protocol(addr, None, dst, loop=loop,
  343. waiter=None, app_protocol_factory=None)
  344. aiosocks.Socks5Protocol(addr, auth, dst, loop=loop,
  345. waiter=None, app_protocol_factory=None)
  346. async def test_socks5_auth_inv_srv_ver(loop):
  347. proto = make_socks5(loop, r=b'\x00\x00')
  348. with pytest.raises(aiosocks.InvalidServerVersion):
  349. await proto.authenticate()
  350. async def test_socks5_auth_no_acceptable_auth_methods(loop):
  351. proto = make_socks5(loop, r=b'\x05\xFF')
  352. with pytest.raises(aiosocks.NoAcceptableAuthMethods):
  353. await proto.authenticate()
  354. async def test_socks5_auth_unsupported_auth_method(loop):
  355. proto = make_socks5(loop, r=b'\x05\xF0')
  356. with pytest.raises(aiosocks.InvalidServerReply):
  357. await proto.authenticate()
  358. async def test_socks5_auth_usr_pwd_granted(loop):
  359. proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x00',))
  360. await proto.authenticate()
  361. proto._stream_writer.write.assert_has_calls([
  362. mock.call(b'\x05\x02\x00\x02'),
  363. mock.call(b'\x01\x04user\x03pwd')
  364. ])
  365. async def test_socks5_auth_usr_pwd_granted_long_usr(loop):
  366. proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x00',), user='0'*200)
  367. await proto.authenticate()
  368. proto._stream_writer.write.assert_has_calls([
  369. mock.call(b'\x05\x02\x00\x02'),
  370. mock.call(b'\x01\xc8' + b'0' * 200 + b'\x03pwd')
  371. ])
  372. async def test_socks5_auth_usr_pwd_granted_long_pwd(loop):
  373. proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x00',), pwd='0'*200)
  374. await proto.authenticate()
  375. proto._stream_writer.write.assert_has_calls([
  376. mock.call(b'\x05\x02\x00\x02'),
  377. mock.call(b'\x01\x04user\xc8' + b'0' * 200)
  378. ])
  379. async def test_socks5_auth_invalid_reply(loop):
  380. proto = make_socks5(loop, r=(b'\x05\x02', b'\x00\x00',))
  381. with pytest.raises(aiosocks.InvalidServerReply):
  382. await proto.authenticate()
  383. async def test_socks5_auth_access_denied(loop):
  384. proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x01',))
  385. with pytest.raises(aiosocks.LoginAuthenticationFailed):
  386. await proto.authenticate()
  387. async def test_socks5_auth_anonymous_granted(loop):
  388. proto = make_socks5(loop, r=b'\x05\x00')
  389. await proto.authenticate()
  390. async def test_socks5_build_dst_addr_ipv4(loop):
  391. proto = make_socks5(loop)
  392. dst_req, resolved = await proto.build_dst_address('127.0.0.1', 80)
  393. assert dst_req == [0x01, b'\x7f\x00\x00\x01', b'\x00P']
  394. assert resolved == ('127.0.0.1', 80)
  395. async def test_socks5_build_dst_addr_ipv6(loop):
  396. proto = make_socks5(loop)
  397. dst_req, resolved = await proto.build_dst_address(
  398. '2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d', 80)
  399. assert dst_req == [
  400. 0x04, b' \x01\r\xb8\x11\xa3\t\xd7\x1f4\x8a.\x07\xa0v]', b'\x00P']
  401. assert resolved == ('2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d', 80)
  402. async def test_socks5_build_dst_addr_domain_with_remote_resolve(loop):
  403. proto = make_socks5(loop)
  404. dst_req, resolved = await proto.build_dst_address('python.org', 80)
  405. assert dst_req == [0x03, b'\n', b'python.org', b'\x00P']
  406. assert resolved == ('python.org', 80)
  407. async def test_socks5_build_dst_addr_domain_with_remote_resolve(loop):
  408. proto = make_socks5(loop)
  409. dst_req, resolved = await proto.build_dst_address('python.org' * 20, 80)
  410. assert dst_req == [0x03, 200, b'python.org' * 20, b'\x00P']
  411. assert resolved == ('python.org' * 20, 80)
  412. async def test_socks5_build_dst_addr_domain_with_locale_resolve(loop):
  413. proto = make_socks5(loop, rr=False)
  414. dst_req, resolved = await proto.build_dst_address('python.org', 80)
  415. assert dst_req == [0x01, b'\x7f\x00\x00\x01', b'\x00P']
  416. assert resolved == ('127.0.0.1', 80)
  417. async def test_socks5_rd_addr_ipv4(loop):
  418. proto = make_socks5(loop, r=[b'\x01', b'\x7f\x00\x00\x01', b'\x00P'])
  419. r = await proto.read_address()
  420. assert r == ('127.0.0.1', 80)
  421. async def test_socks5_rd_addr_ipv6(loop):
  422. resp = [
  423. b'\x04',
  424. b' \x01\r\xb8\x11\xa3\t\xd7\x1f4\x8a.\x07\xa0v]',
  425. b'\x00P'
  426. ]
  427. proto = make_socks5(loop, r=resp)
  428. r = await proto.read_address()
  429. assert r == ('2001:db8:11a3:9d7:1f34:8a2e:7a0:765d', 80)
  430. async def test_socks5_rd_addr_domain(loop):
  431. proto = make_socks5(loop, r=[b'\x03', b'\n', b'python.org', b'\x00P'])
  432. r = await proto.read_address()
  433. assert r == (b'python.org', 80)
  434. async def test_socks5_build_udp_ipv4(loop):
  435. proto = make_socks5(loop)
  436. assert (await proto.build_udp(5, ('1.2.3.4', 16)) ==
  437. b'\x00\x00\x05\x01\x01\x02\x03\x04\x00\x10')
  438. async def test_socks5_parse_udp_ipv4(loop):
  439. proto = make_socks5(loop)
  440. frag, addr, data = proto.parse_udp(b'\x00\x00\x07\x01\x01\x02\x09\x04\x00\x20foobar')
  441. assert frag == 7
  442. assert addr == ('1.2.9.4', 32)
  443. assert data == b'foobar'
  444. async def test_socks5_parse_udp_domain(loop):
  445. proto = make_socks5(loop)
  446. frag, addr, data = proto.parse_udp(b'\x00\x00\x07\x03\x06domain\x00\x20foobar')
  447. assert frag == 7
  448. assert addr == ('domain', 32)
  449. assert data == b'foobar'
  450. async def test_socks5_parse_udp_ipv6(loop):
  451. proto = make_socks5(loop)
  452. frag, addr, data = proto.parse_udp(b'\x00\x00\x07\x04'
  453. b' \x01\r\xb8\x11\xa3\t\xd7\x1f4\x8a.\x07\xa0v]'
  454. b'\x00\x20foobar')
  455. assert frag == 7
  456. assert addr == ('2001:db8:11a3:9d7:1f34:8a2e:7a0:765d', 32)
  457. assert data == b'foobar'
  458. async def test_socks5_parse_udp_invalid(loop):
  459. proto = make_socks5(loop)
  460. for i in [
  461. b'\x01\x00\x07\x01\x01\x02\x09\x04\x00\x20foobar',
  462. b'\x00\x01\x07\x01\x01\x02\x09\x04\x00\x20foobar',
  463. b'\x00\x00\x07\x09\x01\x02\x09\x04\x00\x20foobar',
  464. ]:
  465. with pytest.raises(InvalidServerReply):
  466. proto.parse_udp(i)
  467. async def test_socks5_socks_req_inv_ver(loop):
  468. proto = make_socks5(loop, r=[b'\x05\x00', b'\x04\x00\x00'])
  469. with pytest.raises(aiosocks.InvalidServerVersion):
  470. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  471. async def test_socks5_socks_req_socks_srv_err(loop):
  472. proto = make_socks5(loop, r=[b'\x05\x00', b'\x05\x02\x00'])
  473. with pytest.raises(aiosocks.SocksError) as ct:
  474. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  475. assert 'Connection not allowed by ruleset' in str(ct)
  476. async def test_socks5_socks_req_unknown_err(loop):
  477. proto = make_socks5(loop, r=[b'\x05\x00', b'\x05\xFF\x00'])
  478. with pytest.raises(aiosocks.SocksError) as ct:
  479. await proto.socks_request(c.SOCKS_CMD_CONNECT)
  480. assert 'Unknown error' in str(ct)
  481. async def test_socks_req_cmd_granted(loop):
  482. # cmd granted
  483. resp = [b'\x05\x00',
  484. b'\x05\x00\x00',
  485. b'\x01', b'\x7f\x00\x00\x01',
  486. b'\x00P']
  487. proto = make_socks5(loop, r=resp)
  488. r = await proto.socks_request(c.SOCKS_CMD_CONNECT)
  489. assert r == (('python.org', 80), ('127.0.0.1', 80))
  490. proto._stream_writer.write.assert_has_calls([
  491. mock.call(b'\x05\x02\x00\x02'),
  492. mock.call(b'\x05\x01\x00\x03\npython.org\x00P')
  493. ])