Skip to content

Commit df7830f

Browse files
committed
Handle and ignore permission errors when attempting to read .pgpass
Fixes: MagicStack#356
1 parent 946e2bd commit df7830f

File tree

2 files changed

+59
-14
lines changed

2 files changed

+59
-14
lines changed

‎asyncpg/connect_utils.py‎

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,27 @@
5959
def_read_password_file(passfile: pathlib.Path) \
6060
->typing.List[typing.Tuple[str, ...]]:
6161

62-
ifnotpassfile.is_file():
63-
warnings.warn(
64-
'password file{!r} is not a plain file'.format(passfile))
62+
passtab= []
6563

66-
returnNone
64+
try:
65+
ifnotpassfile.exists():
66+
return []
6767

68-
if_system!='Windows':
69-
ifpassfile.stat().st_mode& (stat.S_IRWXG|stat.S_IRWXO):
68+
ifnotpassfile.is_file():
7069
warnings.warn(
71-
'password file{!r} has group or world access; '
72-
'permissions should be u=rw (0600) or less'.format(passfile))
70+
'password file{!r} is not a plain file'.format(passfile))
7371

74-
returnNone
72+
return[]
7573

76-
passtab= []
74+
if_system!='Windows':
75+
ifpassfile.stat().st_mode& (stat.S_IRWXG|stat.S_IRWXO):
76+
warnings.warn(
77+
'password file{!r} has group or world access; '
78+
'permissions should be u=rw (0600) or less'.format(
79+
passfile))
80+
81+
return []
7782

78-
try:
7983
withpassfile.open('rt') asf:
8084
forlineinf:
8185
line=line.strip()
@@ -105,9 +109,6 @@ def _read_password_from_pgpass(
105109
Password string, if found, ``None`` otherwise.
106110
"""
107111

108-
ifnotpassfile.exists():
109-
returnNone
110-
111112
passtab=_read_password_file(passfile)
112113
ifnotpasstab:
113114
returnNone

‎tests/test_connect.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,50 @@ def test_connect_pgpass_nonexistent(self):
661661
)
662662
})
663663

664+
@unittest.skipIf(_system=='Windows', 'no mode checking on Windows')
665+
deftest_connect_pgpass_inaccessible_file(self):
666+
withtempfile.NamedTemporaryFile('w+t') aspassfile:
667+
os.chmod(passfile.name, stat.S_IWUSR)
668+
669+
# nonexistent passfile is OK
670+
self.run_testcase({
671+
'host': 'abc',
672+
'user': 'user',
673+
'database': 'db',
674+
'passfile': passfile.name,
675+
'result': (
676+
[('abc', 5432)],
677+
{
678+
'user': 'user',
679+
'database': 'db',
680+
}
681+
)
682+
})
683+
684+
@unittest.skipIf(_system=='Windows', 'no mode checking on Windows')
685+
deftest_connect_pgpass_inaccessible_directory(self):
686+
withtempfile.TemporaryDirectory() aspassdir:
687+
withtempfile.NamedTemporaryFile('w+t', dir=passdir) aspassfile:
688+
os.chmod(passdir, stat.S_IWUSR)
689+
690+
try:
691+
# nonexistent passfile is OK
692+
self.run_testcase({
693+
'host': 'abc',
694+
'user': 'user',
695+
'database': 'db',
696+
'passfile': passfile.name,
697+
'result': (
698+
[('abc', 5432)],
699+
{
700+
'user': 'user',
701+
'database': 'db',
702+
}
703+
)
704+
})
705+
finally:
706+
os.chmod(passdir, stat.S_IRWXU)
707+
664708
asyncdeftest_connect_args_validation(self):
665709
forvalin{-1, 'a', True, False, 0}:
666710
withself.assertRaisesRegex(ValueError, 'greater than 0'):

0 commit comments

Comments
(0)