Secure implementation preventing race conditions

This commit is contained in:
Adrien Ferrand 2019-05-25 15:30:00 +02:00
parent 1cc9cc7fb4
commit dbb8549219

View file

@ -1,8 +1,10 @@
"""Compat module to handle files security on Windows and Linux"""
from __future__ import absolute_import
import tempfile
import os # pylint: disable=os-module-forbidden
from certbot.compat import misc
def open(file_path, flags, mode=0o777): # pylint: disable=redefined-builtin
# type: (str, int, int) -> int
@ -16,8 +18,28 @@ def open(file_path, flags, mode=0o777): # pylint: disable=redefined-builtin
:returns: the file descriptor to the opened file
:rtype: int
"""
file_descriptor = os.open(file_path, flags, mode)
# TODO: Change to filesystem.chmod once all logic of windows files permissions has been merged
os.chmod(file_path, mode)
if os.name != 'nt':
return os.open(file_path, flags, mode)
# Windows specific
# In order to avoid race conditions on file access when applying chown() after opening a file,
# we use the capabilities of tempfile.mkstemp() to call chown() before opening the file.
# Indeed, mkstemp() is called if the file does not exist and appropriate flag is set, then
# chown() is invoked, then finally the temporary file is moved on its final location.
# Using this approach, the file is never exposed to the system with loose permissions:
# either it is a secured temporary file with exclusive access to the current user, or proper
# call to chown() has already been applied before the file descriptor is returned.
if not os.path.exists(file_path) and (flags & os.O_CREAT):
file_h, path = tempfile.mkstemp()
os.close(file_h)
# TODO: Change to filesystem.rename once all logic of windows files permissions
# has been merged
misc.os_rename(path, file_path)
if os.path.exists(file_path):
# TODO: Change to filesystem.chmod once all logic of windows files permissions
# has been merged
os.chmod(file_path, mode)
return os.open(file_path, flags)
return file_descriptor