Finish postprocessing script signature checking

CURA-7319
This commit is contained in:
Nino van Hooff 2020-03-24 16:24:24 +01:00
parent 7f89c7e740
commit 5b045f89b1
3 changed files with 101 additions and 17 deletions

View file

@ -1,24 +1,24 @@
# Copyright (c) 2018 Jaime van Kessel, Ultimaker B.V.
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
from typing import Dict, Type, TYPE_CHECKING, List, Optional, cast
from UM.Trust import Trust
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
from UM.Application import Application
from UM.Extension import Extension
from UM.Logger import Logger
import configparser # The script lists are stored in metadata as serialised config files.
import importlib.util
import io # To allow configparser to write to a string.
import os.path
import pkgutil
import sys
import importlib.util
from typing import Dict, Type, TYPE_CHECKING, List, Optional, cast
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
from UM.Application import Application
from UM.Extension import Extension
from UM.Logger import Logger
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
from UM.Trust import Trust
from UM.i18n import i18nCatalog
from cura import ApplicationMetadata
from cura.CuraApplication import CuraApplication
i18n_catalog = i18nCatalog("cura")
@ -162,12 +162,13 @@ class PostProcessingPlugin(QObject, Extension):
# Iterate over all scripts.
if script_name not in sys.modules:
try:
file_location = os.path.join(path, script_name + ".py")
trust_instance = Trust.getInstanceOrNone()
if trust_instance is not None and Trust.signatureFileExistsFor(file_location):
if not trust_instance.signedFileCheck(file_location):
raise Exception("Can't validate script {0}".format(file_location))
spec = importlib.util.spec_from_file_location(__name__ + "." + script_name, file_location)
file_path = os.path.join(path, script_name + ".py")
if not self._isScriptAllowed(file_path):
Logger.warning("Skipped loading post-processing script {}: not trusted".format(file_path))
continue
spec = importlib.util.spec_from_file_location(__name__ + "." + script_name,
file_path)
loaded_script = importlib.util.module_from_spec(spec)
if spec.loader is None:
continue
@ -340,4 +341,22 @@ class PostProcessingPlugin(QObject, Extension):
if global_container_stack is not None:
global_container_stack.propertyChanged.emit("post_processing_plugin", "value")
@staticmethod
def _isScriptAllowed(file_path) -> bool:
"""Checks whether the given file is allowed to be loaded"""
if not ApplicationMetadata.IsEnterpriseVersion:
# No signature needed
return True
if os.path.split(file_path) == os.path.join(Resources.getStoragePath(Resources.Resources), "scripts"):
# Bundled scripts are trusted.
return True
trust_instance = Trust.getInstanceOrNone()
if trust_instance is not None and Trust.signatureFileExistsFor(file_path):
if trust_instance.signedFileCheck(file_path):
return True
return False # Default verdict should be False, being the most secure fallback