diff --git a/RootHelper/uicache.m b/RootHelper/uicache.m index 76e7a69..9ca366b 100644 --- a/RootHelper/uicache.m +++ b/RootHelper/uicache.m @@ -11,33 +11,27 @@ extern NSSet* immutableAppBundleIdentifiers(void); extern NSDictionary* dumpEntitlementsFromBinaryAtPath(NSString* binaryPath); -NSDictionary* constructGroupsContainersForEntitlements(NSDictionary* entitlements, BOOL systemGroups) -{ - if(!entitlements) return nil; +NSDictionary *constructGroupsContainersForEntitlements(NSDictionary *entitlements, BOOL systemGroups) { + if (!entitlements) return nil; - NSString* entitlementForGroups; + NSString *entitlementForGroups; Class mcmClass; - if(systemGroups) - { + if (systemGroups) { entitlementForGroups = @"com.apple.security.system-groups"; mcmClass = [MCMSystemDataContainer class]; } - else - { + else { entitlementForGroups = @"com.apple.security.application-groups"; mcmClass = [MCMSharedDataContainer class]; } - NSArray* groupIDs = entitlements[entitlementForGroups]; - if(groupIDs && [groupIDs isKindOfClass:[NSArray class]]) - { - NSMutableDictionary* groupContainers = [NSMutableDictionary new]; + NSArray *groupIDs = entitlements[entitlementForGroups]; + if (groupIDs && [groupIDs isKindOfClass:[NSArray class]]) { + NSMutableDictionary *groupContainers = [NSMutableDictionary new]; - for(NSString* groupID in groupIDs) - { - MCMContainer* container = [mcmClass containerWithIdentifier:groupID createIfNecessary:YES existed:nil error:nil]; - if(container.url) - { + for (NSString *groupID in groupIDs) { + MCMContainer *container = [mcmClass containerWithIdentifier:groupID createIfNecessary:YES existed:nil error:nil]; + if (container.url) { groupContainers[groupID] = container.url.path; } } @@ -48,22 +42,17 @@ NSDictionary* constructGroupsContainersForEntitlements(NSDictionary* entitlement return nil; } -BOOL constructContainerizationForEntitlements(NSDictionary* entitlements) -{ - NSNumber* noContainer = entitlements[@"com.apple.private.security.no-container"]; - if(noContainer && [noContainer isKindOfClass:[NSNumber class]]) - { - if(noContainer.boolValue) - { +BOOL constructContainerizationForEntitlements(NSDictionary *entitlements) { + NSNumber *noContainer = entitlements[@"com.apple.private.security.no-container"]; + if (noContainer && [noContainer isKindOfClass:[NSNumber class]]) { + if (noContainer.boolValue) { return NO; } } - NSNumber* containerRequired = entitlements[@"com.apple.private.security.container-required"]; - if(containerRequired && [containerRequired isKindOfClass:[NSNumber class]]) - { - if(!containerRequired.boolValue) - { + NSNumber *containerRequired = entitlements[@"com.apple.private.security.container-required"]; + if (containerRequired && [containerRequired isKindOfClass:[NSNumber class]]) { + if (!containerRequired.boolValue) { return NO; } } @@ -71,77 +60,75 @@ BOOL constructContainerizationForEntitlements(NSDictionary* entitlements) return YES; } -NSString* constructTeamIdentifierForEntitlements(NSDictionary* entitlements) -{ - NSString* teamIdentifier = entitlements[@"com.apple.developer.team-identifier"]; - if(teamIdentifier && [teamIdentifier isKindOfClass:[NSString class]]) - { +NSString *constructTeamIdentifierForEntitlements(NSDictionary *entitlements) { + NSString *teamIdentifier = entitlements[@"com.apple.developer.team-identifier"]; + if (teamIdentifier && [teamIdentifier isKindOfClass:[NSString class]]) { return teamIdentifier; } return nil; } -NSDictionary* constructEnvironmentVariablesForContainerPath(NSString* containerPath) -{ - NSString* tmpDir = [containerPath stringByAppendingPathComponent:@"tmp"]; +NSDictionary *constructEnvironmentVariablesForContainerPath(NSString *containerPath, BOOL isContainerized) { + NSString *homeDir = isContainerized ? containerPath : @"/var/mobile"; + NSString *tmpDir = isContainerized ? [containerPath stringByAppendingPathComponent:@"tmp"] : @"/var/tmp"; return @{ - @"CFFIXED_USER_HOME" : containerPath, - @"HOME" : containerPath, + @"CFFIXED_USER_HOME" : homeDir, + @"HOME" : homeDir, @"TMPDIR" : tmpDir }; } -void registerPath(NSString* path, BOOL unregister, BOOL system) -{ - if(!path) return; +void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { + if (!path) return; - LSApplicationWorkspace* workspace = [LSApplicationWorkspace defaultWorkspace]; - if(unregister && ![[NSFileManager defaultManager] fileExistsAtPath:path]) - { - LSApplicationProxy* app = [LSApplicationProxy applicationProxyForIdentifier:path]; - if(app.bundleURL) - { + LSApplicationWorkspace *workspace = [LSApplicationWorkspace defaultWorkspace]; + if (unregister && ![[NSFileManager defaultManager] fileExistsAtPath:path]) { + LSApplicationProxy *app = [LSApplicationProxy applicationProxyForIdentifier:path]; + if (app.bundleURL) { path = [app bundleURL].path; } } - path = [path stringByResolvingSymlinksInPath]; + path = path.stringByResolvingSymlinksInPath.stringByStandardizingPath; - NSDictionary* appInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[path stringByAppendingPathComponent:@"Info.plist"]]; - NSString* appBundleID = [appInfoPlist objectForKey:@"CFBundleIdentifier"]; + NSDictionary *appInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[path stringByAppendingPathComponent:@"Info.plist"]]; + NSString *appBundleID = [appInfoPlist objectForKey:@"CFBundleIdentifier"]; if([immutableAppBundleIdentifiers() containsObject:appBundleID.lowercaseString]) return; - if(appBundleID && !unregister) - { - MCMContainer* appContainer = [NSClassFromString(@"MCMAppDataContainer") containerWithIdentifier:appBundleID createIfNecessary:YES existed:nil error:nil]; - NSString* containerPath = [appContainer url].path; + if (appBundleID && !unregister) { + MCMContainer *appContainer = [NSClassFromString(@"MCMAppDataContainer") containerWithIdentifier:appBundleID createIfNecessary:YES existed:nil error:nil]; + NSString *containerPath = [appContainer url].path; - NSMutableDictionary* dictToRegister = [NSMutableDictionary dictionary]; + BOOL isRemovableSystemApp = [[NSFileManager defaultManager] fileExistsAtPath:[@"/System/Library/AppSignatures" stringByAppendingPathComponent:appBundleID]]; + BOOL registerAsUser = [path hasPrefix:@"/var/containers"] && !isRemovableSystemApp && !forceSystem; + + NSMutableDictionary *dictToRegister = [NSMutableDictionary dictionary]; // Add entitlements - NSString* appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]]; - NSDictionary* entitlements = dumpEntitlementsFromBinaryAtPath(appExecutablePath); - if(entitlements) - { + NSString *appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]]; + NSDictionary *entitlements = dumpEntitlementsFromBinaryAtPath(appExecutablePath); + if (entitlements) { dictToRegister[@"Entitlements"] = entitlements; } + // Misc - - dictToRegister[@"ApplicationType"] = system ? @"System" : @"User"; + + dictToRegister[@"ApplicationType"] = registerAsUser ? @"User" : @"System"; dictToRegister[@"CFBundleIdentifier"] = appBundleID; dictToRegister[@"CodeInfoIdentifier"] = appBundleID; dictToRegister[@"CompatibilityState"] = @0; - if(containerPath) - { + BOOL appContainerized = constructContainerizationForEntitlements(entitlements); + dictToRegister[@"IsContainerized"] = @(appContainerized); + if (containerPath) { dictToRegister[@"Container"] = containerPath; - dictToRegister[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(containerPath); + dictToRegister[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(containerPath, appContainerized); } - dictToRegister[@"IsDeletable"] = @(![appBundleID isEqualToString:@"com.opa334.TrollStore"] && kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_15_0); + dictToRegister[@"IsDeletable"] = @(registerAsUser || isRemovableSystemApp); dictToRegister[@"Path"] = path; - dictToRegister[@"IsContainerized"] = @(constructContainerizationForEntitlements(entitlements)); + dictToRegister[@"SignerOrganization"] = @"Apple Inc."; dictToRegister[@"SignatureVersion"] = @132352; dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing"; @@ -152,24 +139,21 @@ void registerPath(NSString* path, BOOL unregister, BOOL system) dictToRegister[@"FamilyID"] = @0; dictToRegister[@"IsOnDemandInstallCapable"] = @0; - NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements); - if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier; + NSString *teamIdentifier = constructTeamIdentifierForEntitlements(entitlements); + if (teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier; // Add group containers - NSDictionary* appGroupContainers = constructGroupsContainersForEntitlements(entitlements, NO); - NSDictionary* systemGroupContainers = constructGroupsContainersForEntitlements(entitlements, YES); - NSMutableDictionary* groupContainers = [NSMutableDictionary new]; + NSDictionary *appGroupContainers = constructGroupsContainersForEntitlements(entitlements, NO); + NSDictionary *systemGroupContainers = constructGroupsContainersForEntitlements(entitlements, YES); + NSMutableDictionary *groupContainers = [NSMutableDictionary new]; [groupContainers addEntriesFromDictionary:appGroupContainers]; [groupContainers addEntriesFromDictionary:systemGroupContainers]; - if(groupContainers.count) - { - if(appGroupContainers.count) - { + if (groupContainers.count) { + if (appGroupContainers.count) { dictToRegister[@"HasAppGroupContainers"] = @YES; } - if(systemGroupContainers.count) - { + if (systemGroupContainers.count) { dictToRegister[@"HasSystemGroupContainers"] = @YES; } dictToRegister[@"GroupContainers"] = groupContainers.copy; @@ -177,29 +161,27 @@ void registerPath(NSString* path, BOOL unregister, BOOL system) // Add plugins - NSString* pluginsPath = [path stringByAppendingPathComponent:@"PlugIns"]; - NSArray* plugins = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pluginsPath error:nil]; + NSString *pluginsPath = [path stringByAppendingPathComponent:@"PlugIns"]; + NSArray *plugins = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pluginsPath error:nil]; - NSMutableDictionary* bundlePlugins = [NSMutableDictionary dictionary]; - for (NSString* pluginName in plugins) - { - NSString* pluginPath = [pluginsPath stringByAppendingPathComponent:pluginName]; + NSMutableDictionary *bundlePlugins = [NSMutableDictionary dictionary]; + for (NSString *pluginName in plugins) { + NSString *pluginPath = [pluginsPath stringByAppendingPathComponent:pluginName]; - NSDictionary* pluginInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[pluginPath stringByAppendingPathComponent:@"Info.plist"]]; - NSString* pluginBundleID = [pluginInfoPlist objectForKey:@"CFBundleIdentifier"]; + NSDictionary *pluginInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[pluginPath stringByAppendingPathComponent:@"Info.plist"]]; + NSString *pluginBundleID = [pluginInfoPlist objectForKey:@"CFBundleIdentifier"]; - if(!pluginBundleID) continue; - MCMContainer* pluginContainer = [NSClassFromString(@"MCMPluginKitPluginDataContainer") containerWithIdentifier:pluginBundleID createIfNecessary:YES existed:nil error:nil]; - NSString* pluginContainerPath = [pluginContainer url].path; + if (!pluginBundleID) continue; + MCMContainer *pluginContainer = [NSClassFromString(@"MCMPluginKitPluginDataContainer") containerWithIdentifier:pluginBundleID createIfNecessary:YES existed:nil error:nil]; + NSString *pluginContainerPath = [pluginContainer url].path; - NSMutableDictionary* pluginDict = [NSMutableDictionary dictionary]; + NSMutableDictionary *pluginDict = [NSMutableDictionary dictionary]; // Add entitlements - NSString* pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]]; - NSDictionary* pluginEntitlements = dumpEntitlementsFromBinaryAtPath(pluginExecutablePath); - if(pluginEntitlements) - { + NSString *pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]]; + NSDictionary *pluginEntitlements = dumpEntitlementsFromBinaryAtPath(pluginExecutablePath); + if (pluginEntitlements) { pluginDict[@"Entitlements"] = pluginEntitlements; } @@ -209,36 +191,33 @@ void registerPath(NSString* path, BOOL unregister, BOOL system) pluginDict[@"CFBundleIdentifier"] = pluginBundleID; pluginDict[@"CodeInfoIdentifier"] = pluginBundleID; pluginDict[@"CompatibilityState"] = @0; - if(pluginContainerPath) - { + BOOL pluginContainerized = constructContainerizationForEntitlements(pluginEntitlements); + pluginDict[@"IsContainerized"] = @(pluginContainerized); + if (pluginContainerPath) { pluginDict[@"Container"] = pluginContainerPath; - pluginDict[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(pluginContainerPath); + pluginDict[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(pluginContainerPath, pluginContainerized); } pluginDict[@"Path"] = pluginPath; pluginDict[@"PluginOwnerBundleID"] = appBundleID; - pluginDict[@"IsContainerized"] = @(constructContainerizationForEntitlements(pluginEntitlements)); pluginDict[@"SignerOrganization"] = @"Apple Inc."; pluginDict[@"SignatureVersion"] = @132352; pluginDict[@"SignerIdentity"] = @"Apple iPhone OS Application Signing"; - NSString* pluginTeamIdentifier = constructTeamIdentifierForEntitlements(pluginEntitlements); - if(pluginTeamIdentifier) pluginDict[@"TeamIdentifier"] = pluginTeamIdentifier; + NSString *pluginTeamIdentifier = constructTeamIdentifierForEntitlements(pluginEntitlements); + if (pluginTeamIdentifier) pluginDict[@"TeamIdentifier"] = pluginTeamIdentifier; // Add plugin group containers - NSDictionary* pluginAppGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, NO); - NSDictionary* pluginSystemGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, YES); - NSMutableDictionary* pluginGroupContainers = [NSMutableDictionary new]; + NSDictionary *pluginAppGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, NO); + NSDictionary *pluginSystemGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, YES); + NSMutableDictionary *pluginGroupContainers = [NSMutableDictionary new]; [pluginGroupContainers addEntriesFromDictionary:pluginAppGroupContainers]; [pluginGroupContainers addEntriesFromDictionary:pluginSystemGroupContainers]; - if(pluginGroupContainers.count) - { - if(pluginAppGroupContainers.count) - { + if (pluginGroupContainers.count) { + if (pluginAppGroupContainers.count) { pluginDict[@"HasAppGroupContainers"] = @YES; } - if(pluginSystemGroupContainers.count) - { + if (pluginSystemGroupContainers.count) { pluginDict[@"HasSystemGroupContainers"] = @YES; } pluginDict[@"GroupContainers"] = pluginGroupContainers.copy; @@ -248,17 +227,13 @@ void registerPath(NSString* path, BOOL unregister, BOOL system) } [dictToRegister setObject:bundlePlugins forKey:@"_LSBundlePlugins"]; - if(![workspace registerApplicationDictionary:dictToRegister]) - { + if (![workspace registerApplicationDictionary:dictToRegister]) { + NSLog(@"Error: Unable to register %@", path); + } + } else { + NSURL *url = [NSURL fileURLWithPath:path]; + if (![workspace unregisterApplication:url]) { NSLog(@"Error: Unable to register %@", path); } } - else - { - NSURL* url = [NSURL fileURLWithPath:path]; - if(![workspace unregisterApplication:url]) - { - NSLog(@"Error: Unable to unregister %@", path); - } - } }