Skip to content

Commit

Permalink
Fix handling of non-ASCII passwords (#1062)
Browse files Browse the repository at this point in the history
Fixes: #1018
  • Loading branch information
elprans committed Aug 17, 2023
1 parent 922fcd1 commit 89d5bd0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 17 deletions.
10 changes: 5 additions & 5 deletions asyncpg/protocol/coreproto.pyx
Expand Up @@ -642,7 +642,7 @@ cdef class CoreProtocol:
WriteBuffer msg

msg = WriteBuffer.new_message(b'p')
msg.write_bytestring(self.password.encode('ascii'))
msg.write_bytestring(self.password.encode(self.encoding))
msg.end_message()

return msg
Expand All @@ -654,11 +654,11 @@ cdef class CoreProtocol:
msg = WriteBuffer.new_message(b'p')

# 'md5' + md5(md5(password + username) + salt))
userpass = ((self.password or '') + (self.user or '')).encode('ascii')
hash = hashlib.md5(hashlib.md5(userpass).hexdigest().\
encode('ascii') + salt).hexdigest().encode('ascii')
userpass = (self.password or '') + (self.user or '')
md5_1 = hashlib.md5(userpass.encode(self.encoding)).hexdigest()
md5_2 = hashlib.md5(md5_1.encode('ascii') + salt).hexdigest()

msg.write_bytestring(b'md5' + hash)
msg.write_bytestring(b'md5' + md5_2.encode('ascii'))
msg.end_message()

return msg
Expand Down
27 changes: 15 additions & 12 deletions tests/test_connect.py
Expand Up @@ -126,6 +126,9 @@ def test_server_version_02(self):
self.assertEqual(expected, result)


CORRECT_PASSWORD = 'correct\u1680password'


class TestAuthentication(tb.ConnectedTestCase):
def setUp(self):
super().setUp()
Expand All @@ -136,9 +139,9 @@ def setUp(self):
methods = [
('trust', None),
('reject', None),
('scram-sha-256', 'correctpassword'),
('md5', 'correctpassword'),
('password', 'correctpassword'),
('scram-sha-256', CORRECT_PASSWORD),
('md5', CORRECT_PASSWORD),
('password', CORRECT_PASSWORD),
]

self.cluster.reset_hba()
Expand All @@ -160,7 +163,7 @@ def setUp(self):
create_script.append(
'CREATE ROLE {}_user WITH LOGIN{};'.format(
username,
' PASSWORD {!r}'.format(password) if password else ''
f' PASSWORD E{(password or "")!r}'
)
)

Expand Down Expand Up @@ -250,7 +253,7 @@ async def test_auth_reject(self):
async def test_auth_password_cleartext(self):
conn = await self.connect(
user='password_user',
password='correctpassword')
password=CORRECT_PASSWORD)
await conn.close()

with self.assertRaisesRegex(
Expand All @@ -262,7 +265,7 @@ async def test_auth_password_cleartext(self):

async def test_auth_password_cleartext_callable(self):
def get_correctpassword():
return 'correctpassword'
return CORRECT_PASSWORD

def get_wrongpassword():
return 'wrongpassword'
Expand All @@ -281,7 +284,7 @@ def get_wrongpassword():

async def test_auth_password_cleartext_callable_coroutine(self):
async def get_correctpassword():
return 'correctpassword'
return CORRECT_PASSWORD

async def get_wrongpassword():
return 'wrongpassword'
Expand All @@ -300,7 +303,7 @@ async def get_wrongpassword():

async def test_auth_password_cleartext_callable_awaitable(self):
async def get_correctpassword():
return 'correctpassword'
return CORRECT_PASSWORD

async def get_wrongpassword():
return 'wrongpassword'
Expand All @@ -319,7 +322,7 @@ async def get_wrongpassword():

async def test_auth_password_md5(self):
conn = await self.connect(
user='md5_user', password='correctpassword')
user='md5_user', password=CORRECT_PASSWORD)
await conn.close()

with self.assertRaisesRegex(
Expand All @@ -334,7 +337,7 @@ async def test_auth_password_scram_sha_256(self):
return

conn = await self.connect(
user='scram_sha_256_user', password='correctpassword')
user='scram_sha_256_user', password=CORRECT_PASSWORD)
await conn.close()

with self.assertRaisesRegex(
Expand Down Expand Up @@ -371,7 +374,7 @@ async def test_auth_password_scram_sha_256(self):
await conn.close()

alter_password = \
"ALTER ROLE scram_sha_256_user PASSWORD 'correctpassword';"
f"ALTER ROLE scram_sha_256_user PASSWORD E{CORRECT_PASSWORD!r};"
await self.con.execute(alter_password)
await self.con.execute("SET password_encryption = 'md5';")

Expand All @@ -381,7 +384,7 @@ async def test_auth_md5_unsupported(self, _):
exceptions.InternalClientError,
".*no md5.*",
):
await self.connect(user='md5_user', password='correctpassword')
await self.connect(user='md5_user', password=CORRECT_PASSWORD)


class TestConnectParams(tb.TestCase):
Expand Down

0 comments on commit 89d5bd0

Please sign in to comment.