diff --git a/AltServer/Devices/ALTDeviceManager.mm b/AltServer/Devices/ALTDeviceManager.mm index 4ed7ebd8..287c922a 100644 --- a/AltServer/Devices/ALTDeviceManager.mm +++ b/AltServer/Devices/ALTDeviceManager.mm @@ -14,6 +14,7 @@ #include #include #include +#include void ALTDeviceManagerUpdateStatus(plist_t command, plist_t status, void *udid); @@ -64,18 +65,52 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError"; strncpy(uuidString, (const char *)UUID.UUIDString.UTF8String, UUID.UUIDString.length); uuidString[UUID.UUIDString.length] = '\0'; - idevice_t device = NULL; - lockdownd_client_t client = NULL; - instproxy_client_t ipc = NULL; - np_client_t np = NULL; - afc_client_t afc = NULL; - lockdownd_service_descriptor_t service = NULL; + __block idevice_t device = NULL; + __block lockdownd_client_t client = NULL; + __block instproxy_client_t ipc = NULL; + __block afc_client_t afc = NULL; + __block misagent_client_t mis = NULL; + __block lockdownd_service_descriptor_t service = NULL; + + NSURL *removedProfilesDirectoryURL = [[[NSFileManager defaultManager] temporaryDirectory] URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]]; void (^finish)(NSError *error) = ^(NSError *error) { + if ([[NSFileManager defaultManager] fileExistsAtPath:removedProfilesDirectoryURL.path isDirectory:nil]) + { + // Reinstall all provisioning profiles we removed before installation. + + NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:removedProfilesDirectoryURL.path error:nil]; + for (NSString *filename in contents) + { + NSURL *fileURL = [removedProfilesDirectoryURL URLByAppendingPathComponent:filename]; + + ALTProvisioningProfile *provisioningProfile = [[ALTProvisioningProfile alloc] initWithURL:fileURL]; + if (provisioningProfile == nil) + { + continue; + } + + plist_t pdata = plist_new_data((const char *)provisioningProfile.data.bytes, provisioningProfile.data.length); + + if (misagent_install(mis, pdata) == MISAGENT_E_SUCCESS) + { + NSLog(@"Reinstalled profile: %@", provisioningProfile.identifier); + } + else + { + int code = misagent_get_status_code(mis); + NSLog(@"Failed to reinstall provisioning profile %@. (%@)", provisioningProfile.identifier, @(code)); + } + } + + [[NSFileManager defaultManager] removeItemAtURL:removedProfilesDirectoryURL error:nil]; + } + instproxy_client_free(ipc); afc_client_free(afc); lockdownd_client_free(client); + misagent_client_free(mis); idevice_free(device); lockdownd_service_descriptor_free(service); @@ -206,7 +241,83 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError"; NSLog(@"Finished writing to device."); - NSProgress *installationProgress = [NSProgress progressWithTotalUnitCount:100 parent:progress pendingUnitCount:1]; + /* Provisioning Profiles */ + NSURL *provisioningProfileURL = [appBundleURL URLByAppendingPathComponent:@"embedded.mobileprovision"]; + ALTProvisioningProfile *installationProvisioningProfile = [[ALTProvisioningProfile alloc] initWithURL:provisioningProfileURL]; + if (installationProvisioningProfile != nil) + { + NSError *error = nil; + if (![[NSFileManager defaultManager] createDirectoryAtURL:removedProfilesDirectoryURL withIntermediateDirectories:YES attributes:nil error:&error]) + { + return finish(error); + } + + if ((lockdownd_start_service(client, "com.apple.misagent", &service) != LOCKDOWN_E_SUCCESS) || service == NULL) + { + return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]); + } + + if (misagent_client_new(device, service, &mis) != MISAGENT_E_SUCCESS) + { + return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]); + } + + plist_t profiles = NULL; + if (misagent_copy_all(mis, &profiles) != MISAGENT_E_SUCCESS) + { + return finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]); + } + + uint32_t profileCount = plist_array_get_size(profiles); + for (int i = 0; i < profileCount; i++) + { + plist_t profile = plist_array_get_item(profiles, i); + if (plist_get_node_type(profile) != PLIST_DATA) + { + continue; + } + + char *bytes = NULL; + uint64_t length = 0; + + plist_get_data_val(profile, &bytes, &length); + if (bytes == NULL) + { + continue; + } + + NSData *data = [NSData dataWithBytes:(const void *)bytes length:length]; + ALTProvisioningProfile *provisioningProfile = [[ALTProvisioningProfile alloc] initWithData:data]; + + if (![provisioningProfile.teamIdentifier isEqualToString:installationProvisioningProfile.teamIdentifier]) + { + continue; + } + + NSString *filename = [NSString stringWithFormat:@"%@.mobileprovision", [[NSUUID UUID] UUIDString]]; + NSURL *fileURL = [removedProfilesDirectoryURL URLByAppendingPathComponent:filename]; + + NSError *copyError = nil; + if (![provisioningProfile.data writeToURL:fileURL options:NSDataWritingAtomic error:©Error]) + { + NSLog(@"Failed to copy profile to temporary URL. %@", copyError); + continue; + } + + if (misagent_remove(mis, provisioningProfile.identifier.UTF8String) == MISAGENT_E_SUCCESS) + { + NSLog(@"Removed provisioning profile: %@", provisioningProfile.identifier); + } + else + { + int code = misagent_get_status_code(mis); + NSLog(@"Failed to remove provisioning profile %@. Error Code: %@", provisioningProfile.identifier, @(code)); + } + } + + lockdownd_client_free(client); + client = NULL; + } NSProgress *installationProgress = [NSProgress progressWithTotalUnitCount:100 parent:progress pendingUnitCount:1]; diff --git a/AltServer/ViewController.swift b/AltServer/ViewController.swift index bd754dce..ee13167c 100644 --- a/AltServer/ViewController.swift +++ b/AltServer/ViewController.swift @@ -246,7 +246,7 @@ private extension ViewController { let certificates = try Result(certificates, error).get() - guard let certificate = certificates.first(where: { $0.identifier == certificate.identifier }) else { + guard let certificate = certificates.first(where: { $0.serialNumber == certificate.serialNumber }) else { throw InstallError.missingCertificate } diff --git a/AltStore/Components/Keychain.swift b/AltStore/Components/Keychain.swift index 6d295274..a7cadc27 100644 --- a/AltStore/Components/Keychain.swift +++ b/AltStore/Components/Keychain.swift @@ -26,7 +26,7 @@ class Keychain self.appleIDEmailAddress = nil self.appleIDPassword = nil self.signingCertificatePrivateKey = nil - self.signingCertificateIdentifier = nil + self.signingCertificateSerialNumber = nil } } @@ -62,13 +62,13 @@ extension Keychain } } - var signingCertificateIdentifier: String? { + var signingCertificateSerialNumber: String? { get { - let identifier = try? self.keychain.get("signingCertificateIdentifier") - return identifier + let serialNumber = try? self.keychain.get("signingCertificateSerialNumber") + return serialNumber } set { - self.keychain["signingCertificateIdentifier"] = newValue + self.keychain["signingCertificateSerialNumber"] = newValue } } } diff --git a/AltStore/Operations/AuthenticationOperation.swift b/AltStore/Operations/AuthenticationOperation.swift index bcb0b622..081734ee 100644 --- a/AltStore/Operations/AuthenticationOperation.swift +++ b/AltStore/Operations/AuthenticationOperation.swift @@ -138,7 +138,7 @@ class AuthenticationOperation: ResultOperation Keychain.shared.appleIDEmailAddress = altAccount.appleID // "account" may have nil appleID since we just saved. Keychain.shared.appleIDPassword = self.appleIDPassword - Keychain.shared.signingCertificateIdentifier = signer.certificate.identifier + Keychain.shared.signingCertificateSerialNumber = signer.certificate.serialNumber Keychain.shared.signingCertificatePrivateKey = signer.certificate.privateKey super.finish(.success(signer)) @@ -299,7 +299,7 @@ private extension AuthenticationOperation { let certificates = try Result(certificates, error).get() - guard let certificate = certificates.first(where: { $0.identifier == certificate.identifier }) else { + guard let certificate = certificates.first(where: { $0.serialNumber == certificate.serialNumber }) else { throw AuthenticationError.missingCertificate } @@ -349,9 +349,9 @@ private extension AuthenticationOperation let certificates = try Result(certificates, error).get() if - let identifier = Keychain.shared.signingCertificateIdentifier, + let serialNumber = Keychain.shared.signingCertificateSerialNumber, let privateKey = Keychain.shared.signingCertificatePrivateKey, - let certificate = certificates.first(where: { $0.identifier == identifier }) + let certificate = certificates.first(where: { $0.serialNumber == serialNumber }) { certificate.privateKey = privateKey completionHandler(.success(certificate)) diff --git a/Dependencies/AltSign b/Dependencies/AltSign index c99aa73a..ae919bed 160000 --- a/Dependencies/AltSign +++ b/Dependencies/AltSign @@ -1 +1 @@ -Subproject commit c99aa73a89fb16e27823476032a5b2e7e16118f0 +Subproject commit ae919bedd259d65584d54fc6861b1cb5261cad8f