Commit a5306278 authored by Vincent Pelletier's avatar Vincent Pelletier

caucase.utils: Tolerate broken symlinks

Otherwise, this causes an IOError to be raised in _getPEMTypeDict.
So move file existence check inside the loop. Also rely on isdir returning
False on non-existent inputs.
This may for example happen if openssl-rehash is used on these directories:
caucase-updater may delete an expired CA, breaking its symlink, triggering
this bug and crashing caucase-updater.
parent ba693499
......@@ -3,6 +3,7 @@
* Janitorial: make updated code checkers happier.
* Explicitly depend on ipaddress module on python 2.7 .
* Be less sensitive to small client/server time disagreements.
* Fix crashes when encountering broken symlinks in directories of PEM files.
0.9.13 (2021-12-22)
===================
......
......@@ -3384,6 +3384,9 @@ class CaucaseTest(TestCase):
utils.getCRLList(self._client_ca_dir),
[crl0_pem, crl1_pem],
)
# Broken symlink: does not get deleted, and does not cause errors
broken_symlink = os.path.join(self._client_ca_dir, 'is_a_trap')
os.symlink('does_not_exist', broken_symlink)
# On with the test for the CA side
utils.saveCertList(self._client_ca_dir, [crt0_pem])
self.assertTrue(os.path.exists(self._client_ca_dir))
......@@ -3404,6 +3407,7 @@ class CaucaseTest(TestCase):
utils.saveCertList(self._client_ca_dir, [crt0_pem])
self.assertTrue(os.path.exists(kept_file_path))
self.assertFalse(os.path.exists(deleted_file_path))
self.assertTrue(os.path.lexists(broken_symlink))
os.unlink(kept_file_path)
# Storing and loading multiple certificates
utils.saveCertList(self._client_ca_dir, [crt0_pem, crt1_pem])
......@@ -3430,6 +3434,8 @@ class CaucaseTest(TestCase):
utils.getCRLList(self._client_ca_dir),
[crl0_pem, crl1_pem],
)
# The borken symlink is still present
self.assertTrue(os.path.lexists(broken_symlink))
def testHttpSSLRenewal(self):
"""
......
......@@ -152,17 +152,17 @@ def getCRLList(crl_path):
return _getPEMListFromPath(crl_path, pem.CertificateRevocationList)
def _getPEMListFromPath(path, pem_type):
if not os.path.exists(path):
return []
return [
pem_object.as_bytes()
for file_name in (
[os.path.join(path, x) for x in os.listdir(path)]
if os.path.isdir(path) else
[path]
)
for pem_object in _getPEMTypeDict(file_name).get(pem_type, ())
]
result = []
for file_name in (
[os.path.join(path, x) for x in os.listdir(path)]
if os.path.isdir(path) else
[path]
):
# path is missing, or a symlink in path (if path is a directory) is broken
if os.path.exists(file_name):
for pem_object in _getPEMTypeDict(file_name).get(pem_type, ()):
result.append(pem_object.as_bytes())
return result
def saveCertList(crt_path, cert_pem_list):
"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment