Example #1
0
    def checkDigest(self, downloadRetriesLeft=3):
        CraftCore.log.debug("ArchiveSource.checkDigest called")
        filenames = self.localFileNames()

        if self.subinfo.hasTargetDigestUrls():
            CraftCore.log.debug("check digests urls")
            if not CraftHash.checkFilesDigests(self.__downloadDir, filenames):
                CraftCore.log.error("invalid digest file")
                redownload = downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                    "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                    default="Yes")
                if redownload:
                    for filename in filenames:
                        CraftCore.log.info(
                            f"Deleting downloaded file: {filename}")
                        utils.deleteFile(
                            os.path.join(self.__downloadDir, filename))
                        for digestAlgorithm, digestFileEnding in CraftHash.HashAlgorithm.fileEndings(
                        ).items():
                            digestFileName = filename + digestFileEnding
                            if os.path.exists(
                                    os.path.join(self.__downloadDir,
                                                 digestFileName)):
                                CraftCore.log.info(
                                    f"Deleting downloaded file: {digestFileName}"
                                )
                                utils.deleteFile(
                                    os.path.join(self.__downloadDir,
                                                 digestFileName))
                    return self.fetch() and self.checkDigest(
                        downloadRetriesLeft - 1)
                return False
        elif self.subinfo.hasTargetDigests():
            CraftCore.log.debug("check digests")
            digests, algorithm = self.subinfo.targetDigest()
            if not CraftHash.checkFilesDigests(self.__downloadDir, filenames,
                                               digests, algorithm):
                CraftCore.log.error("invalid digest file")
                redownload = downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                    "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                    default="Yes")
                if redownload:
                    for filename in filenames:
                        CraftCore.log.info(
                            f"Deleting downloaded file: {filename}")
                        utils.deleteFile(
                            os.path.join(self.__downloadDir, filename))
                    return self.fetch() and self.checkDigest(
                        downloadRetriesLeft - 1)
                return False
        else:
            CraftCore.log.debug("print source file digests")
            CraftHash.printFilesDigests(
                self.__downloadDir,
                filenames,
                self.subinfo.buildTarget,
                algorithm=CraftHash.HashAlgorithm.SHA256)
        return True
Example #2
0
 def __retry(self, downloadRetriesLeft : int, func, **kw):
     downloadRetriesLeft -= 1
     if downloadRetriesLeft >= 0 and CraftChoicePrompt.promptForChoice("Do you want to delete the files and redownload them?",
                                                                 [("Yes", True), ("No", False)],
                                                                 default="Yes"):
         return func(downloadRetriesLeft=downloadRetriesLeft, **kw)
     return False
Example #3
0
    def __unlock(self):
        if self._useCertFile:
            password = secrets.token_urlsafe(16)
            if not utils.system(["security", "create-keychain", "-p", password, self.loginKeychain], stdout=subprocess.DEVNULL, secret=[password]):
                return False
            # FIXME: Retain original list: security list-keychains -d user -s "${KEYCHAIN}" $(security list-keychains -d user | sed s/\"//g)
            if not utils.system(["security", "list-keychains", "-d", "user", "-s", self.loginKeychain], stdout=subprocess.DEVNULL, secret=[password]):
                return False

            def importCert(cert, pwKey):
                pw  = CraftChoicePrompt.promptForPassword(message=f"Enter the password for certificate: {Path(cert).name}", key=pwKey)
                return utils.system(["security", "import", cert, "-k", self.loginKeychain, "-P", pw, "-T", "/usr/bin/codesign", "-T", "/usr/bin/productsign"], stdout=subprocess.DEVNULL, secret=[password, pw])

            if self.certFileApplication:
                if not importCert(self.certFileApplication, "MAC_CERTIFICATE_APPLICATION_PASSWORD"):
                    return False
            if self.certFilesInstaller:
                if not importCert(self.certFilesInstaller, "MAC_CERTIFICATE_INSTALLER_PASSWORD"):
                    return False
            if not utils.system(["security", "set-key-partition-list", "-S", "apple-tool:,apple:,codesign:", "-s", "-k", password, self.loginKeychain], stdout=subprocess.DEVNULL, secret=[password]):
                CraftCore.log.error("Failed to set key partition list.")
                return False
        else:
            if CraftCore.settings.getboolean("CodeSigning", "Protected", False):
                password = CraftChoicePrompt.promptForPassword(message="Enter the password for your signing keychain", key="MAC_KEYCHAIN_PASSWORD")
                if not utils.system(["security", "unlock-keychain", "-p", password, self.loginKeychain], stdout=subprocess.DEVNULL, secret=[password]):
                    CraftCore.log.error("Failed to unlock keychain.")
                    return False

        return True
Example #4
0
 def importCert(cert, pwKey):
     pw = CraftChoicePrompt.promptForPassword(
         message=
         f"Enter the password for certificate: {Path(cert).name}",
         key=pwKey)
     return utils.system([
         "security", "import", cert, "-k", self.loginKeychain, "-P",
         pw, "-T", "/usr/bin/codesign", "-T", "/usr/bin/productsign"
     ],
                         stdout=subprocess.DEVNULL,
                         secret=[password])
Example #5
0
def signWindows(fileNames: [str]) -> bool:
    if not CraftCore.settings.getboolean("CodeSigning", "Enabled", False):
        return True
    if not CraftCore.compiler.isWindows:
        CraftCore.log.warning(
            "Code signing is currently only supported on Windows")
        return True

    signTool = CraftCore.cache.findApplication("signtool", forceCache=True)
    if not signTool:
        env = SetupHelper.getMSVCEnv()
        signTool = CraftCore.cache.findApplication("signtool",
                                                   env["PATH"],
                                                   forceCache=True)
    if not signTool:
        CraftCore.log.warning(
            "Code signing requires a VisualStudio installation")
        return False

    command = [
        signTool, "sign", "/tr", "http://timestamp.digicert.com", "/td",
        "SHA256", "/fd", "SHA256", "/a"
    ]
    certFile = CraftCore.settings.get("CodeSigning", "Certificate", "")
    subjectName = CraftCore.settings.get("CodeSigning", "CommonName", "")
    certProtected = CraftCore.settings.getboolean("CodeSigning", "Protected",
                                                  False)
    kwargs = dict()
    if certFile:
        command += ["/f", certFile]
    if subjectName:
        command += ["/n", subjectName]
    if certProtected:
        password = CraftChoicePrompt.promptForPassword(
            message='Enter the password for your package signing certificate',
            key="WINDOWS_CODE_SIGN_CERTIFICATE_PASSWORD")
        command += ["/p", password]
        kwargs["secret"] = [password]
    if True or CraftCore.debug.verbose() > 0:
        command += ["/v"]
    else:
        command += ["/q"]
    for args in utils.limitCommandLineLength(command, fileNames):
        if not utils.system(args, **kwargs):
            return False
    return True
Example #6
0
    def fetchBinary(self, downloadRetriesLeft=3) -> bool:
        if self.subinfo.options.package.disableBinaryCache:
            return False
        for url in [self.cacheLocation()] + self.cacheRepositoryUrls():
            CraftCore.log.debug(f"Trying to restore {self} from cache: {url}.")
            if url == self.cacheLocation():
                fileUrl = f"{url}/manifest.json"
                if os.path.exists(fileUrl):
                    with open(fileUrl, "rt", encoding="UTF-8") as f:
                        manifest = CraftManifest.fromJson(json.load(f))
                else:
                    continue
            else:
                manifest = CraftManifest.fromJson(
                    CraftCore.cache.cacheJsonFromUrl(f"{url}/manifest.json"))
            fileEntry = manifest.get(str(self)).files
            files = []
            for f in fileEntry:
                if f.version == self.version:
                    files.append(f)
            if not files:
                CraftCore.log.info(
                    f"Could not find {self}={self.version} in {url}")
                continue
            latest = files[0]

            if not self.subinfo.options.dynamic.compatible(
                    latest.config, latest.configHash):
                CraftCore.log.info(
                    "Failed to restore package, configuration missmatch")
                CraftCore.debug.debug_line()
                CraftCore.log.info("Cached config: {}".format(", ".join(
                    f"{k}={v}" for k, v in latest.config.items())))
                CraftCore.log.info(
                    f"Local config:  {self.subinfo.options.dynamic}")
                CraftCore.debug.debug_line()
                # try next cache
                continue

            # if we are creating the cache, a rebuild on a failed fetch would be suboptimal
            createingCache = CraftCore.settings.getboolean(
                "Packager", "CreateCache", False)

            if url != self.cacheLocation():
                downloadFolder = self.cacheLocation(
                    os.path.join(CraftCore.standardDirs.downloadDir(),
                                 "cache"))
            else:
                downloadFolder = self.cacheLocation()
            localArchiveAbsPath = OsUtils.toNativePath(
                os.path.join(downloadFolder, latest.fileName))
            localArchivePath, localArchiveName = os.path.split(
                localArchiveAbsPath)

            if url != self.cacheLocation():
                if not os.path.exists(localArchiveAbsPath):
                    os.makedirs(localArchivePath, exist_ok=True)
                    fileName = latest.fileName
                    if CraftCore.compiler.isWindows:
                        fileName = fileName.replace("\\", "/")
                    fUrl = f"{url}/{fileName}"
                    # try it up to 3 times
                    retries = 3
                    while True:
                        if GetFiles.getFile(fUrl, localArchivePath,
                                            localArchiveName):
                            break
                        msg = f"Failed to fetch {fUrl}"
                        retries -= 1
                        if not retries:
                            if createingCache:
                                raise BlueprintException(msg, self.package)
                            else:
                                CraftCore.log.warning(msg)
                            return False
            elif not os.path.isfile(localArchiveAbsPath):
                continue

            if not CraftHash.checkFilesDigests(
                    localArchivePath, [localArchiveName],
                    digests=latest.checksum,
                    digestAlgorithm=CraftHash.HashAlgorithm.SHA256):
                msg = f"Hash did not match, {localArchiveName} might be corrupted"
                CraftCore.log.warning(msg)
                if downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                        "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                        default="Yes"):
                    return utils.deleteFile(
                        localArchiveAbsPath) and self.fetchBinary(
                            downloadRetriesLeft=downloadRetriesLeft - 1)
                if createingCache:
                    raise BlueprintException(msg, self.package)
                return False
            self.subinfo.buildPrefix = latest.buildPrefix
            self.subinfo.isCachedBuild = True
            if not (self.cleanImage() and utils.unpackFile(
                    localArchivePath, localArchiveName, self.imageDir())
                    and self.internalPostInstall() and self.postInstall()
                    and self.qmerge() and self.internalPostQmerge()
                    and self.postQmerge()):
                return False
            return True
        return False
Example #7
0
    def fetchBinary(self, downloadRetriesLeft=3) -> bool:
        if self.subinfo.options.package.disableBinaryCache:
            return False

        for url in [self.cacheLocation()] + self.cacheRepositoryUrls():
            CraftCore.log.debug(f"Trying to restore {self} from cache: {url}.")
            if url == self.cacheLocation():
                fileUrl = f"{url}/manifest.json"
                if os.path.exists(fileUrl):
                    with open(fileUrl, "rt", encoding="UTF-8") as f:
                        manifest = CraftManifest.fromJson(json.load(f))
                else:
                    continue
            else:
                manifest = CraftManifest.fromJson(
                    CraftCore.cache.cacheJsonFromUrl(f"{url}/manifest.json"))
            fileEntry = manifest.get(str(self)).files
            files = []
            for f in fileEntry:
                if f.version == self.version:
                    files.append(f)
            latest = None
            if not files:
                CraftCore.log.debug(
                    f"Could not find {self}={self.version} in {url}")
                continue
            latest = files[0]

            if url != self.cacheLocation():
                downloadFolder = self.cacheLocation(
                    os.path.join(CraftCore.standardDirs.downloadDir(),
                                 "cache"))
            else:
                downloadFolder = self.cacheLocation()
            localArchiveAbsPath = OsUtils.toNativePath(
                os.path.join(downloadFolder, latest.fileName))
            localArchivePath, localArchiveName = os.path.split(
                localArchiveAbsPath)

            if url != self.cacheLocation():
                if not os.path.exists(localArchiveAbsPath):
                    os.makedirs(localArchivePath, exist_ok=True)
                    fUrl = f"{url}/{latest.fileName}"
                    if not GetFiles.getFile(fUrl, localArchivePath,
                                            localArchiveName):
                        CraftCore.log.warning(f"Failed to fetch {fUrl}")
                        return False
            elif not os.path.isfile(localArchiveAbsPath):
                continue

            if not CraftHash.checkFilesDigests(
                    localArchivePath, [localArchiveName],
                    digests=latest.checksum,
                    digestAlgorithm=CraftHash.HashAlgorithm.SHA256):
                CraftCore.log.warning(
                    f"Hash did not match, {localArchiveName} might be corrupted"
                )
                if downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                        "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                        default="Yes"):
                    return utils.deleteFile(
                        localArchiveAbsPath) and self.fetchBinary(
                            downloadRetriesLeft=downloadRetriesLeft - 1)
                return False
            self.subinfo.buildPrefix = latest.buildPrefix
            self.subinfo.isCachedBuild = True
            if not (self.cleanImage() and utils.unpackFile(
                    localArchivePath, localArchiveName, self.imageDir())
                    and self.internalPostInstall() and self.postInstall()
                    and self.qmerge() and self.internalPostQmerge()
                    and self.postQmerge()):
                return False
            return True
        return False