Skip to content

asyngpg swallows error related to FIPS and MD5 #861

Closed
@eseglem

Description

@eseglem
  • asyncpg version: 0.23.0 - 0.25.0
  • PostgreSQL version: 13.3, and 9.6.22 for additional testing
  • Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
    the issue with a local PostgreSQL install?
    : Using RDS primarily. Issue happens anywhere.
  • Python version: 3.8.11, also reproduced in 3.6.8
  • Platform: CentOS 7
  • Do you use pgbouncer?: No
  • Did you install asyncpg with pip?: Yes
  • If you built asyncpg locally, which version of Cython did you use?: n/a
  • Can the issue be reproduced under both asyncio and
    uvloop?
    : Yes

With FIPS mode enabled, md5 is not allowed. And if asyncpg attempts to connect to a DB using md5 authentication if produced a timeout error. Obviously there is an issue connection with a db configured to use md5, and I was able to connect once it was updated to use SCRAM instead, but it took forever to figure out what the issue was due to how the error is handled.

Simple script:

import asyncio
import asyncpg

async def main():
    print("start")
    c = await asyncpg.connect("postgresql://...")
    print("end")

asyncio.get_event_loop().run_until_complete(main())

In 0.25.0 it says 'start' then hangs for a minute and then produces this stack trace:

Traceback (most recent call last):
  File "test_async.py", line 9, in <module>
    asyncio.get_event_loop().run_until_complete(main())
  File "/opt/rh/rh-python38/root/lib64/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "test_async.py", line 6, in main
    c = await asyncpg.connect("postgresql://...")
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/connection.py", line 2085, in connect
    return await connect_utils._connect(
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/connect_utils.py", line 895, in _connect
    raise last_error
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/connect_utils.py", line 881, in _connect
    return await _connect_addr(
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/connect_utils.py", line 781, in _connect_addr
    return await __connect_addr(params, timeout, True, *args)
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/connect_utils.py", line 831, in __connect_addr
    await compat.wait_for(connected, timeout=timeout)
  File "/home/maintuser/venv/lib64/python3.8/site-packages/asyncpg/compat.py", line 66, in wait_for
    return await asyncio.wait_for(fut, timeout)
  File "/opt/rh/rh-python38/root/lib64/python3.8/asyncio/tasks.py", line 501, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The use of md5 is https://github.com/MagicStack/asyncpg/blob/master/asyncpg/protocol/coreproto.pyx#L637 unfortunately I don't know where that is getting wrapped up and ending up a timeout.

For reference this is the error you get if you try to use hashlib.md5 on a FIPS enabled machine:

$ python
Python 3.8.11 (default, Sep  1 2021, 12:33:46)
[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for fips

I would expect that ValueError, or something along those lines, should be making it back to me, but somehow it gets caught in a loop inside until it hits the timeout. I am guessing there is an an except in there is catching too much, but without being familiar with the codebase I haven't found it yet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions