From dacd616ea3029406bb9ab19f7e4328c77a600bf5 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Thu, 5 Dec 2019 01:11:15 -0800 Subject: [PATCH] fix issue w/ encoding long fields, use to_bytes instead of .encode.. .encode defaults to utf-8, which will end up being two bytes for strings >= 128. --- aiosocks/protocols.py | 6 +++--- tests/test_protocols.py | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/aiosocks/protocols.py b/aiosocks/protocols.py index 0488756..1c69f0b 100644 --- a/aiosocks/protocols.py +++ b/aiosocks/protocols.py @@ -319,8 +319,8 @@ class Socks5Protocol(BaseSocksProtocol): ) if chosen_auth[1] == c.SOCKS5_AUTH_UNAME_PWD: - req = [0x01, chr(len(self._auth.login)).encode(), self._auth.login, - chr(len(self._auth.password)).encode(), self._auth.password] + req = [0x01, len(self._auth.login).to_bytes(1, 'big'), self._auth.login, + len(self._auth.password).to_bytes(1, 'big'), self._auth.password] self.write_request(req) auth_status = await self.read_response(2) @@ -361,7 +361,7 @@ class Socks5Protocol(BaseSocksProtocol): # it's not an IP number, so it's probably a DNS name. if self._remote_resolve: host_bytes = host.encode('idna') - req = [c.SOCKS5_ATYP_DOMAIN, chr(len(host_bytes)).encode(), + req = [c.SOCKS5_ATYP_DOMAIN, len(host_bytes).to_bytes(1, 'big'), host_bytes, port_bytes] else: family, host_bytes = await self._get_dst_addr() diff --git a/tests/test_protocols.py b/tests/test_protocols.py index d242be6..121fd9c 100644 --- a/tests/test_protocols.py +++ b/tests/test_protocols.py @@ -38,9 +38,9 @@ def make_socks4(loop, *, addr=None, auth=None, rr=True, dst=None, r=b'', def make_socks5(loop, *, addr=None, auth=None, rr=True, dst=None, r=None, - ap_factory=None, whiter=None): + ap_factory=None, whiter=None, user='user', pwd='pwd'): addr = addr or aiosocks.Socks5Addr('localhost', 1080) - auth = auth or aiosocks.Socks5Auth('user', 'pwd') + auth = auth or aiosocks.Socks5Auth(user, pwd) dst = dst or ('python.org', 80) proto = aiosocks.Socks5Protocol( @@ -497,6 +497,26 @@ async def test_socks5_auth_usr_pwd_granted(loop): ]) +async def test_socks5_auth_usr_pwd_granted_long_usr(loop): + proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x00',), user='0'*200) + await proto.authenticate() + + proto._stream_writer.write.assert_has_calls([ + mock.call(b'\x05\x02\x00\x02'), + mock.call(b'\x01\xc8' + b'0' * 200 + b'\x03pwd') + ]) + + +async def test_socks5_auth_usr_pwd_granted_long_pwd(loop): + proto = make_socks5(loop, r=(b'\x05\x02', b'\x01\x00',), pwd='0'*200) + await proto.authenticate() + + proto._stream_writer.write.assert_has_calls([ + mock.call(b'\x05\x02\x00\x02'), + mock.call(b'\x01\x04user\xc8' + b'0' * 200) + ]) + + async def test_socks5_auth_invalid_reply(loop): proto = make_socks5(loop, r=(b'\x05\x02', b'\x00\x00',)) @@ -542,6 +562,14 @@ async def test_socks5_build_dst_addr_domain_with_remote_resolve(loop): assert resolved == ('python.org', 80) +async def test_socks5_build_dst_addr_domain_with_remote_resolve(loop): + proto = make_socks5(loop) + dst_req, resolved = await proto.build_dst_address('python.org' * 20, 80) + + assert dst_req == [0x03, b'\xc8', b'python.org' * 20, b'\x00P'] + assert resolved == ('python.org' * 20, 80) + + async def test_socks5_build_dst_addr_domain_with_locale_resolve(loop): proto = make_socks5(loop, rr=False) dst_req, resolved = await proto.build_dst_address('python.org', 80)