From a3318b1253416f4b2b2abaceb2a33ab8b754c00a Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Fri, 26 Feb 2021 21:08:10 -0600 Subject: [PATCH 1/4] Fixes AltDaemon untrusting apps on iOS 14 Refreshing with provisioning profiles causes apps to become untrusted on iOS 14 or later. As a (hopefully) temporary workaround, we instead now always re-install apps to refresh them on iOS 14+ jailbroken devices, which does still work as expected. --- AltStore/Managing Apps/AppManager.swift | 4 +++- AltStoreCore/Extensions/UserDefaults+AltStore.swift | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index ca241cce..8292154a 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -667,12 +667,14 @@ private extension AppManager case .refresh(let app): // Check if backup app is installed in place of real app. let uti = UTTypeCopyDeclaration(app.installedBackupAppUTI as CFString)?.takeRetainedValue() as NSDictionary? - if app.certificateSerialNumber != group.context.certificate?.serialNumber || uti != nil || app.needsResign + + if app.certificateSerialNumber != group.context.certificate?.serialNumber || uti != nil || app.needsResign || (UIDevice.current.isJailbroken && !UserDefaults.standard.localServerSupportsRefreshing) { // Resign app instead of just refreshing profiles because either: // * Refreshing using different certificate // * Backup app is still installed // * App explicitly needs resigning + // * Device is jailbroken and on iOS 14.0 or later (b/c refreshing with provisioning profiles is broken) let installProgress = self._install(app, operation: operation, group: group) { (result) in self.finish(operation, result: result, group: group, progress: progress) diff --git a/AltStoreCore/Extensions/UserDefaults+AltStore.swift b/AltStoreCore/Extensions/UserDefaults+AltStore.swift index 4c0dfe3d..db828fc6 100644 --- a/AltStoreCore/Extensions/UserDefaults+AltStore.swift +++ b/AltStoreCore/Extensions/UserDefaults+AltStore.swift @@ -33,6 +33,8 @@ public extension UserDefaults @NSManaged var isLegacyDeactivationSupported: Bool @NSManaged var activeAppLimitIncludesExtensions: Bool + @NSManaged var localServerSupportsRefreshing: Bool + var activeAppsLimit: Int? { get { return self._activeAppsLimit?.intValue @@ -56,10 +58,14 @@ public extension UserDefaults let isLegacyDeactivationSupported = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios13_5) let activeAppLimitIncludesExtensions = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios13_5) + let ios14 = OperatingSystemVersion(majorVersion: 14, minorVersion: 0, patchVersion: 0) + let localServerSupportsRefreshing = !ProcessInfo.processInfo.isOperatingSystemAtLeast(ios14) + let defaults = [ #keyPath(UserDefaults.isBackgroundRefreshEnabled): true, #keyPath(UserDefaults.isLegacyDeactivationSupported): isLegacyDeactivationSupported, #keyPath(UserDefaults.activeAppLimitIncludesExtensions): activeAppLimitIncludesExtensions, + #keyPath(UserDefaults.localServerSupportsRefreshing): localServerSupportsRefreshing, #keyPath(UserDefaults.requiresAppGroupMigration): true ] From cbcd5fbd2cf5538574c4fa177a350afa5d1fbe57 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Fri, 26 Feb 2021 21:08:31 -0600 Subject: [PATCH 2/4] Updates app version to 1.4.4 --- AltStore.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index e97f69c3..8dac03b3 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -3242,8 +3242,8 @@ "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 1.4.4; PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore; - MARKETING_VERSION = 1.4.3b2; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h"; @@ -3270,8 +3270,8 @@ "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 1.4.4; PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore; - MARKETING_VERSION = 1.4.3b2; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h"; From 729b2a1f0d786819f1819a9f0869a6f6dfce227e Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Mon, 1 Mar 2021 12:41:33 -0600 Subject: [PATCH 3/4] Limits iOS 14 AltDaemon workaround to only when using AltDaemon Refreshing with AltServer while jailbroken will now continue using provisioning profiles, but AltDaemon will still reinstall apps instead of just refreshing them. --- AltStore/Managing Apps/AppManager.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index 8292154a..f66d1f2b 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -668,13 +668,16 @@ private extension AppManager // Check if backup app is installed in place of real app. let uti = UTTypeCopyDeclaration(app.installedBackupAppUTI as CFString)?.takeRetainedValue() as NSDictionary? - if app.certificateSerialNumber != group.context.certificate?.serialNumber || uti != nil || app.needsResign || (UIDevice.current.isJailbroken && !UserDefaults.standard.localServerSupportsRefreshing) + if app.certificateSerialNumber != group.context.certificate?.serialNumber || + uti != nil || + app.needsResign || + (group.context.server?.connectionType == .local && !UserDefaults.standard.localServerSupportsRefreshing) { // Resign app instead of just refreshing profiles because either: // * Refreshing using different certificate // * Backup app is still installed // * App explicitly needs resigning - // * Device is jailbroken and on iOS 14.0 or later (b/c refreshing with provisioning profiles is broken) + // * Device is jailbroken and using AltDaemon on iOS 14.0 or later (b/c refreshing with provisioning profiles is broken) let installProgress = self._install(app, operation: operation, group: group) { (result) in self.finish(operation, result: result, group: group, progress: progress) From 2157d95c564b34f3f566f1e32faaefa48b8912bb Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Mon, 1 Mar 2021 12:45:57 -0600 Subject: [PATCH 4/4] Fixes serial operations not running in FIFO order Ensures AltStore is always the last app to be refreshed, which matters when AltStore needs to be resigned and reinstalled (such as when using AltDaemon on iOS 14). --- AltStore/Managing Apps/AppManager.swift | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index f66d1f2b..7785f37d 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -1403,12 +1403,26 @@ private extension AppManager func run(_ operations: [Foundation.Operation], context: OperationContext?, requiresSerialQueue: Bool = false) { + // Reference to previous serial operation in context used to enforce FIFO, + // even if the operations become ready in a different order than submitted. + var previousSerialOperation: Foundation.Operation? = context?.operations.allObjects.filter { self.serialOperationQueue.operations.contains($0) }.last + for operation in operations { switch operation { case _ where requiresSerialQueue: fallthrough - case is InstallAppOperation, is RefreshAppOperation, is BackupAppOperation: self.serialOperationQueue.addOperation(operation) + case is InstallAppOperation, is RefreshAppOperation, is BackupAppOperation: + if let previousOperation = previousSerialOperation + { + // Add dependency on previous serial operation to enforce FIFO. + operation.addDependency(previousOperation) + } + + self.serialOperationQueue.addOperation(operation) + + previousSerialOperation = operation + default: self.operationQueue.addOperation(operation) }