Exemplo n.º 1
0
    def acquire(self):
        """Acquire the lock"""
        open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC

        fd = None
        try:
            # Under Windows, filesystem.open will raise directly an EACCES error
            # if the lock file is already locked.
            fd = filesystem.open(self._path, open_mode, 0o600)
            # The need for this "type: ignore" was fixed in
            # https://github.com/python/typeshed/pull/3607 and included in
            # newer versions of mypy so it can be removed when mypy is
            # upgraded.
            msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)  # type: ignore
        except (IOError, OSError) as err:
            if fd:
                os.close(fd)
            # Anything except EACCES is unexpected. Raise directly the error in that case.
            if err.errno != errno.EACCES:
                raise
            logger.debug('A lock on %s is held by another process.',
                         self._path)
            raise errors.LockError(
                'Another instance of Certbot is already running.')

        self._fd = fd
Exemplo n.º 2
0
    def acquire(self):
        """Acquire the lock"""
        open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC

        fd = None
        try:
            # Under Windows, filesystem.open will raise directly an EACCES error
            # if the lock file is already locked.
            fd = filesystem.open(self._path, open_mode, 0o600)
            # This "type: ignore" is currently needed because msvcrt methods
            # are only defined on Windows. See
            # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi.
            msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)  # type: ignore
        except (IOError, OSError) as err:
            if fd:
                os.close(fd)
            # Anything except EACCES is unexpected. Raise directly the error in that case.
            if err.errno != errno.EACCES:
                raise
            logger.debug('A lock on %s is held by another process.',
                         self._path)
            raise errors.LockError(
                'Another instance of Certbot is already running.')

        self._fd = fd
Exemplo n.º 3
0
 def _create_file(path, mode=0o777):
     file_desc = None
     try:
         file_desc = filesystem.open(path, flags=os.O_CREAT, mode=mode)
     finally:
         if file_desc:
             os.close(file_desc)
Exemplo n.º 4
0
    def test_not_executable(self):
        file_path = os.path.join(self.tempdir, "foo")

        # On Windows a file created within Certbot will always have all permissions to the
        # Administrators group set. Since the unit tests are typically executed under elevated
        # privileges, it means that current user will always have effective execute rights on the
        # hook script, and so the test will fail. To prevent that and represent a file created
        # outside Certbot as typically a hook file is, we mock the _generate_dacl function in
        # certbot.compat.filesystem to give rights only to the current user. This implies removing
        # all ACEs except the first one from the DACL created by original _generate_dacl function.

        from certbot.compat.filesystem import _generate_dacl

        def _execute_mock(user_sid, mode):
            dacl = _generate_dacl(user_sid, mode)
            for _ in range(1, dacl.GetAceCount()):
                dacl.DeleteAce(
                    1
                )  # DeleteAce dynamically updates the internal index mapping.
            return dacl

        # create a non-executable file
        with mock.patch("certbot.compat.filesystem._generate_dacl",
                        side_effect=_execute_mock):
            os.close(
                filesystem.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666))

        self.assertFalse(filesystem.is_executable(file_path))
Exemplo n.º 5
0
 def test_not_executable(self):
     file_path = os.path.join(self.tempdir, "foo")
     # create a non-executable file
     os.close(os.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666))
     # prevent unnecessary modifications to PATH
     with mock.patch("certbot.hooks.plug_util.path_surgery"):
         self.assertRaises(errors.HookCommandNotFound, self._call,
                           file_path, "foo")
Exemplo n.º 6
0
 def test_not_executable(self):
     file_path = os.path.join(self.tempdir, "foo")
     # create a non-executable file
     os.close(os.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666))
     # prevent unnecessary modifications to PATH
     with mock.patch("certbot.hooks.plug_util.path_surgery"):
         self.assertRaises(errors.HookCommandNotFound,
                           self._call, file_path, "foo")
Exemplo n.º 7
0
    def test_new_file_correct_permissions(self):
        path = os.path.join(self.tempdir, 'file')

        desc = filesystem.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o700)
        os.close(desc)

        dacl = _get_security_dacl(path).GetSecurityDescriptorDacl()
        everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID)

        self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount())
                          if dacl.GetAce(index)[2] == everybody])
Exemplo n.º 8
0
    def _test_one_creation(self, num, file_exist, flags):
        one_file = os.path.join(self.tempdir, str(num))
        if file_exist and not os.path.exists(one_file):
            with open(one_file, 'w'):
                pass

        handler = None
        try:
            handler = filesystem.open(one_file, flags)
        finally:
            if handler:
                os.close(handler)
Exemplo n.º 9
0
    def _test_one_creation(self, num, file_exist, flags):
        one_file = os.path.join(self.tempdir, str(num))
        if file_exist and not os.path.exists(one_file):
            open(one_file, 'w').close()

        handler = None
        try:
            handler = filesystem.open(one_file, flags)
        except BaseException as err:
            if handler:
                os.close(handler)
            raise err
Exemplo n.º 10
0
 def acquire(self) -> None:
     """Acquire the lock."""
     while self._fd is None:
         # Open the file
         fd = filesystem.open(self._path, os.O_CREAT | os.O_WRONLY, 0o600)
         try:
             self._try_lock(fd)
             if self._lock_success(fd):
                 self._fd = fd
         finally:
             # Close the file if it is not the required one
             if self._fd is None:
                 os.close(fd)
Exemplo n.º 11
0
    def release(self):
        """Release the lock."""
        try:
            msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1)
            os.close(self._fd)

            try:
                os.remove(self._path)
            except OSError as e:
                # If the lock file cannot be removed, it is not a big deal.
                # Likely another instance is acquiring the lock we just released.
                logger.debug(str(e))
        finally:
            self._fd = None
Exemplo n.º 12
0
 def acquire(self):
     # type: () -> None
     """Acquire the lock."""
     while self._fd is None:
         # Open the file
         fd = os.open(self._path, os.O_CREAT | os.O_WRONLY, 0o600)
         try:
             self._try_lock(fd)
             if self._lock_success(fd):
                 self._fd = fd
         finally:
             # Close the file if it is not the required one
             if self._fd is None:
                 os.close(fd)
Exemplo n.º 13
0
    def release(self):
        """Release the lock."""
        try:
            msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1)
            os.close(self._fd)

            try:
                os.remove(self._path)
            except OSError as e:
                # If the lock file cannot be removed, it is not a big deal.
                # Likely another instance is acquiring the lock we just released.
                logger.debug(str(e))
        finally:
            self._fd = None
Exemplo n.º 14
0
    def acquire(self):
        """Acquire the lock"""
        open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC

        fd = os.open(self._path, open_mode, 0o600)
        try:
            msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
        except (IOError, OSError) as err:
            os.close(fd)
            # Anything except EACCES is unexpected. Raise directly the error in that case.
            if err.errno != errno.EACCES:
                raise
            logger.debug('A lock on %s is held by another process.', self._path)
            raise errors.LockError('Another instance of Certbot is already running.')

        self._fd = fd
Exemplo n.º 15
0
    def release(self):
        """Release the lock."""
        try:
            # This "type: ignore" is currently needed because msvcrt methods
            # are only defined on Windows. See
            # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi.
            msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1)  # type: ignore
            os.close(self._fd)

            try:
                os.remove(self._path)
            except OSError as e:
                # If the lock file cannot be removed, it is not a big deal.
                # Likely another instance is acquiring the lock we just released.
                logger.debug(str(e))
        finally:
            self._fd = None
Exemplo n.º 16
0
    def acquire(self):
        """Acquire the lock"""
        open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC

        fd = os.open(self._path, open_mode, 0o600)
        try:
            msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
        except (IOError, OSError) as err:
            os.close(fd)
            # Anything except EACCES is unexpected. Raise directly the error in that case.
            if err.errno != errno.EACCES:
                raise
            logger.debug('A lock on %s is held by another process.',
                         self._path)
            raise errors.LockError(
                'Another instance of Certbot is already running.')

        self._fd = fd
Exemplo n.º 17
0
    def release(self):
        """Release the lock."""
        try:
            # The need for this "type: ignore" was fixed in
            # https://github.com/python/typeshed/pull/3607 and included in
            # newer versions of mypy so it can be removed when mypy is
            # upgraded.
            msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1)  # type: ignore
            os.close(self._fd)

            try:
                os.remove(self._path)
            except OSError as e:
                # If the lock file cannot be removed, it is not a big deal.
                # Likely another instance is acquiring the lock we just released.
                logger.debug(str(e))
        finally:
            self._fd = None
Exemplo n.º 18
0
 def release(self) -> None:
     """Remove, close, and release the lock file."""
     # It is important the lock file is removed before it's released,
     # otherwise:
     #
     # process A: open lock file
     # process B: release lock file
     # process A: lock file
     # process A: check device and inode
     # process B: delete file
     # process C: open and lock a different file at the same path
     try:
         os.remove(self._path)
     finally:
         # Following check is done to make mypy happy: it ensure that self._fd, marked
         # as Optional[int] is effectively int to make it compatible with os.close signature.
         if self._fd is None:  # pragma: no cover
             raise TypeError('Error, self._fd is None.')
         try:
             os.close(self._fd)
         finally:
             self._fd = None
Exemplo n.º 19
0
 def release(self):
     # type: () -> None
     """Remove, close, and release the lock file."""
     # It is important the lock file is removed before it's released,
     # otherwise:
     #
     # process A: open lock file
     # process B: release lock file
     # process A: lock file
     # process A: check device and inode
     # process B: delete file
     # process C: open and lock a different file at the same path
     try:
         os.remove(self._path)
     finally:
         # Following check is done to make mypy happy: it ensure that self._fd, marked
         # as Optional[int] is effectively int to make it compatible with os.close signature.
         if self._fd is None:  # pragma: no cover
             raise TypeError('Error, self._fd is None.')
         try:
             os.close(self._fd)
         finally:
             self._fd = None