示例#1
0
		IList<MobileProvision> GetProvisioningProfiles (MobileProvisionPlatform platform, MobileProvisionDistributionType type, CodeSignIdentity identity, IList<X509Certificate2> certs)
		{
			var failures = new List<string> ();
			IList<MobileProvision> profiles;

			if (identity.BundleId != null) {
				if (certs.Count > 0)
					profiles = MobileProvisionIndex.GetMobileProvisions (platform, identity.BundleId, type, certs, unique: true, failures: failures);
				else
					profiles = MobileProvisionIndex.GetMobileProvisions (platform, identity.BundleId, type, unique: true, failures: failures);
			} else if (certs.Count > 0) {
				profiles = MobileProvisionIndex.GetMobileProvisions (platform, type, certs, unique: true, failures: failures);
			} else {
				profiles = MobileProvisionIndex.GetMobileProvisions (platform, type, unique: true, failures: failures);
			}

			if (profiles.Count == 0) {
				foreach (var f in failures)
					Log.LogMessage (MessageImportance.Low, "{0}", f);
				
				Log.LogError (MSBStrings.E0131, AppBundleName, PlatformName);
				return null;
			}

			Log.LogMessage (MessageImportance.Low, "Available profiles:");
			foreach (var p in profiles)
				Log.LogMessage (MessageImportance.Low, "    {0}", p.Name);

			return profiles;
		}
示例#2
0
        public override bool Execute()
        {
            var profile = MobileProvisionIndex.GetMobileProvision(GetMobileProvisionPlatform(), ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError(MSBStrings.E0049, ProvisioningProfile);
                return(false);
            }

            var embedded = EmbeddedProvisionProfilePath;

            if (File.Exists(embedded))
            {
                var embeddedProfile = MobileProvision.LoadFromFile(embedded);

                if (embeddedProfile.Uuid == profile.Uuid)
                {
                    return(true);
                }
            }

            Directory.CreateDirectory(Path.GetDirectoryName(embedded));
            profile.Save(embedded);

            return(true);
        }
示例#3
0
        public void TestOpenIndex()
        {
            var index = MobileProvisionIndex.OpenIndex("../../TestData/Provisioning Profiles", "profiles.index");

            Assert.AreEqual(2, index.ProvisioningProfiles.Count);

            Assert.AreEqual("YHT9CR87YA.com.companyname.*", index.ProvisioningProfiles[0].ApplicationIdentifier);
            Assert.AreEqual(new DateTime(2017, 07, 19, 19, 43, 45, DateTimeKind.Utc), index.ProvisioningProfiles[0].CreationDate);
            Assert.AreEqual(1, index.ProvisioningProfiles[0].DeveloperCertificates.Count);
            Assert.AreEqual("iPhone Developer: Jeffrey Stedfast (FZ77UAV9SW)", index.ProvisioningProfiles[0].DeveloperCertificates[0].Name);
            Assert.AreEqual("2097D37F4D16AB7D8D927E7C1872F2A94D8DC718", index.ProvisioningProfiles[0].DeveloperCertificates[0].Thumbprint);
            Assert.AreEqual(MobileProvisionDistributionType.Development, index.ProvisioningProfiles[0].Distribution);
            Assert.AreEqual(new DateTime(2018, 07, 19, 19, 43, 45, DateTimeKind.Utc), index.ProvisioningProfiles[0].ExpirationDate);
            Assert.AreEqual("29cbf4b4-a170-4c74-a29a-64ecd55b102e.mobileprovision", Path.GetFileName(index.ProvisioningProfiles[0].FileName));
            //Assert.AreEqual (index.ProvisioningProfiles[0].LastModified);
            Assert.AreEqual("CompanyName Development Profile", index.ProvisioningProfiles[0].Name);
            Assert.AreEqual(1, index.ProvisioningProfiles[0].Platforms.Count);
            Assert.AreEqual(MobileProvisionPlatform.iOS, index.ProvisioningProfiles[0].Platforms[0]);
            Assert.AreEqual("29cbf4b4-a170-4c74-a29a-64ecd55b102e", index.ProvisioningProfiles[0].Uuid);

            Assert.AreEqual("YHT9CR87YA.com.xamarin.*", index.ProvisioningProfiles[1].ApplicationIdentifier);
            Assert.AreEqual(new DateTime(2017, 07, 19, 19, 44, 0, DateTimeKind.Utc), index.ProvisioningProfiles[1].CreationDate);
            Assert.AreEqual(1, index.ProvisioningProfiles[1].DeveloperCertificates.Count);
            Assert.AreEqual("iPhone Developer: Jeffrey Stedfast (FZ77UAV9SW)", index.ProvisioningProfiles[1].DeveloperCertificates[0].Name);
            Assert.AreEqual("2097D37F4D16AB7D8D927E7C1872F2A94D8DC718", index.ProvisioningProfiles[1].DeveloperCertificates[0].Thumbprint);
            Assert.AreEqual(MobileProvisionDistributionType.Development, index.ProvisioningProfiles[1].Distribution);
            Assert.AreEqual(new DateTime(2018, 07, 19, 19, 44, 0, DateTimeKind.Utc), index.ProvisioningProfiles[1].ExpirationDate);
            Assert.AreEqual("7079f389-6ff4-4290-bf76-c8a222947616.mobileprovision", Path.GetFileName(index.ProvisioningProfiles[1].FileName));
            //Assert.AreEqual (index.ProvisioningProfiles[0].LastModified);
            Assert.AreEqual("Xamarin Development Profile", index.ProvisioningProfiles[1].Name);
            Assert.AreEqual(1, index.ProvisioningProfiles[1].Platforms.Count);
            Assert.AreEqual(MobileProvisionPlatform.iOS, index.ProvisioningProfiles[1].Platforms[0]);
            Assert.AreEqual("7079f389-6ff4-4290-bf76-c8a222947616", index.ProvisioningProfiles[1].Uuid);
        }
示例#4
0
        public override bool Execute()
        {
            Log.LogTaskName("EmbedMobileProvision");
            Log.LogTaskProperty("AppBundleDir", AppBundleDir);
            Log.LogTaskProperty("ProvisioningProfile", ProvisioningProfile);

            var profile = MobileProvisionIndex.GetMobileProvision(MobileProvisionPlatform.iOS, ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError("Could not locate the provisioning profile with a Name or UUID of {0}.", ProvisioningProfile);
                return(false);
            }

            var embedded = Path.Combine(AppBundleDir, "embedded.mobileprovision");

            if (File.Exists(embedded))
            {
                var embeddedProfile = MobileProvision.LoadFromFile(embedded);

                if (embeddedProfile.Uuid == profile.Uuid)
                {
                    return(true);
                }
            }

            Directory.CreateDirectory(AppBundleDir);
            profile.Save(embedded);

            return(true);
        }
        public override bool Execute()
        {
            MobileProvisionPlatform platform;

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            case "MacCatalyst":
                platform = MobileProvisionPlatform.MacOS;
                break;

            default:
                Log.LogError(MSBStrings.E0048, SdkPlatform);
                return(false);
            }

            var profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError(MSBStrings.E0049, ProvisioningProfile);
                return(false);
            }

            var embedded = Path.Combine(AppBundleDir, "embedded.mobileprovision");

            if (File.Exists(embedded))
            {
                var embeddedProfile = MobileProvision.LoadFromFile(embedded);

                if (embeddedProfile.Uuid == profile.Uuid)
                {
                    return(true);
                }
            }

            Directory.CreateDirectory(AppBundleDir);
            profile.Save(embedded);

            return(true);
        }
        public override bool Execute()
        {
            MobileProvisionPlatform platform;

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            default:
                Log.LogError("Unknown SDK platform: {0}", SdkPlatform);
                return(false);
            }

            var profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError("Could not locate the provisioning profile with a Name or UUID of {0}.", ProvisioningProfile);
                return(false);
            }

            var embedded = Path.Combine(AppBundleDir, "embedded.mobileprovision");

            if (File.Exists(embedded))
            {
                var embeddedProfile = MobileProvision.LoadFromFile(embedded);

                if (embeddedProfile.Uuid == profile.Uuid)
                {
                    return(true);
                }
            }

            Directory.CreateDirectory(AppBundleDir);
            profile.Save(embedded);

            return(true);
        }
        public override bool Execute()
        {
            var profile = MobileProvisionIndex.GetMobileProvision(MobileProvisionPlatform.MacOS, ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError(MSBStrings.E0049, ProvisioningProfile);
                return(false);
            }

            var embedded = Path.Combine(AppBundleDir, "Contents", "embedded.provisionprofile");

            Directory.CreateDirectory(AppBundleDir);
            profile.Save(embedded);

            return(true);
        }
示例#8
0
        IList <MobileProvision> GetProvisioningProfiles(MobileProvisionPlatform platform, MobileProvisionDistributionType type, CodeSignIdentity identity, IList <X509Certificate2> certs)
        {
            var failures = new List <string> ();
            IList <MobileProvision> profiles;

            if (identity.BundleId != null)
            {
                if (certs.Count > 0)
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type, certs, unique: true, failures: failures);
                }
                else
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type, unique: true, failures: failures);
                }
            }
            else if (certs.Count > 0)
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type, certs, unique: true, failures: failures);
            }
            else
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type, unique: true, failures: failures);
            }

            if (profiles.Count == 0)
            {
                foreach (var f in failures)
                {
                    Log.LogMessage(MessageImportance.Low, "{0}", f);
                }

                Log.LogError($"Could not find any available provisioning profiles for {PlatformName}. Please enable Automatic Provisioning from the iOS Bundle Signing page.");

                return(null);
            }

            Log.LogMessage(MessageImportance.Low, "Available profiles:");

            foreach (var p in profiles)
            {
                Log.LogMessage(MessageImportance.Low, "    {0}", p.Name);
            }

            return(profiles);
        }
示例#9
0
        public override bool Execute()
        {
            var profile = MobileProvisionIndex.GetMobileProvision(MobileProvisionPlatform.MacOS, ProvisioningProfile);

            if (profile == null)
            {
                Log.LogError("Could not locate the provisioning profile with a Name or UUID of {0}.", ProvisioningProfile);
                return(false);
            }

            var embedded = Path.Combine(AppBundleDir, "Contents", "embedded.provisionprofile");

            Directory.CreateDirectory(AppBundleDir);
            profile.Save(embedded);

            return(true);
        }
示例#10
0
 protected virtual MobileProvision GetMobileProvision(MobileProvisionPlatform platform, string name)
 {
     return(MobileProvisionIndex.GetMobileProvision(platform, name));
 }
示例#11
0
        public override bool Execute()
        {
            PDictionary              plist;
            IList <MobileProvision>  profiles;
            IList <X509Certificate2> certs;
            List <CodeSignIdentity>  pairs;

            var type     = GetProvisioningDistributionType();
            var platform = MobileProvisionPlatform.iOS;
            var identity = new CodeSignIdentity();

            hotRestartClient = new HotRestartClient();

            try {
                plist = PDictionary.FromFile(AppManifest);
            } catch (Exception ex) {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Error loading '{0}': {1}", AppManifest, ex.Message);

                return(false);
            }

            identity.BundleId = plist.GetCFBundleIdentifier();

            if (string.IsNullOrEmpty(identity.BundleId))
            {
                if (GenerateApplicationManifest && !string.IsNullOrEmpty(ApplicationId))
                {
                    identity.BundleId = ApplicationId;
                }
                else
                {
                    Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "{0} does not define CFBundleIdentifier", AppManifest);

                    return(false);
                }
            }

            DetectedBundleId = identity.BundleId;

            var appDisplayName = plist.GetCFBundleDisplayName();

            if (string.IsNullOrEmpty(appDisplayName))
            {
                if (GenerateApplicationManifest && !string.IsNullOrEmpty(ApplicationTitle))
                {
                    appDisplayName = ApplicationTitle;
                }
            }

            DetectedAppDisplayName = appDisplayName;

            if (!TryGetSigningCertificates(out certs, false))
            {
                return(false);
            }

            Log.LogMessage(MessageImportance.Low, "Available certificates:");

            foreach (var cert in certs)
            {
                Log.LogMessage(MessageImportance.Low, "    {0}", GetCertificateCommonName(cert));
            }

            if (!IsAutoCodeSignProfile(ProvisioningProfile))
            {
                identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                if (identity.Profile == null)
                {
                    Log.LogError("The specified " + PlatformName + " provisioning profile '{0}' could not be found. Please enable Automatic Provisioning from the iOS Bundle Signing page.", ProvisioningProfile);
                    return(false);
                }

                var profile = identity.Profile;                 // capture ref for lambda

                if (certs.Count > 0)
                {
                    identity.SigningKey = certs.FirstOrDefault(c => profile.DeveloperCertificates.Any(p => p.Thumbprint == c.Thumbprint));
                    if (identity.SigningKey == null)
                    {
                        Log.LogError("No " + PlatformName + " signing identities match the specified provisioning profile '{0}'.", ProvisioningProfile);
                        return(false);
                    }
                }

                identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);

                if (identity.AppId == null)
                {
                    Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId, ProvisioningProfile);
                    return(false);
                }

                if (identity.SigningKey != null)
                {
                    codesignCommonName      = GetCertificateCommonName(identity.SigningKey);
                    DetectedCodeSigningPath = Path.Combine(CertificatesPath, $"{identity.SigningKey.SerialNumber}.p12");
                }

                provisioningProfileName = identity.Profile.Name;

                DetectedAppId = identity.AppId;
                DetectedProvisioningProfileId   = identity.Profile.Uuid;
                DetectedProvisioningProfilePath = Path.Combine(ProfilesPath, $"{DetectedProvisioningProfileId}.mobileprovision");

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if ((profiles = GetProvisioningProfiles(platform, type, identity, certs)) == null)
            {
                return(false);
            }

            if ((pairs = GetCodeSignIdentityPairs(profiles, certs)) == null)
            {
                return(false);
            }

            identity = GetBestMatch(pairs, identity);

            if (identity.Profile != null && identity.AppId != null)
            {
                codesignCommonName = identity.SigningKey != null?GetCertificateCommonName(identity.SigningKey) : null;

                provisioningProfileName = identity.Profile.Name;

                DetectedAppId           = identity.AppId;
                DetectedCodeSigningPath = identity.SigningKey != null?Path.Combine(CertificatesPath, $"{identity.SigningKey.SerialNumber}.p12") : string.Empty;

                DetectedProvisioningProfileId   = identity.Profile.Uuid;
                DetectedProvisioningProfilePath = Path.Combine(ProfilesPath, $"{DetectedProvisioningProfileId}.mobileprovision");

                ReportDetectedCodesignInfo();
            }
            else
            {
                if (identity.SigningKey != null)
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId, identity.SigningKey);
                }
                else
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var type     = MobileProvisionDistributionType.Any;
            var identity = new CodeSignIdentity();
            MobileProvisionPlatform  platform;
            IList <MobileProvision>  profiles;
            IList <X509Certificate2> certs;
            List <CodeSignIdentity>  pairs;

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            case "MacOSX":
                platform = MobileProvisionPlatform.MacOS;
                break;

            case "MacCatalyst":
                platform = MobileProvisionPlatform.MacOS;
                break;

            default:
                Log.LogError(MSBStrings.E0048, SdkPlatform);
                return(false);
            }

            if (ProvisioningProfile == AutomaticAppStoreProvision)
            {
                type = MobileProvisionDistributionType.AppStore;
            }
            else if (ProvisioningProfile == AutomaticInHouseProvision)
            {
                type = MobileProvisionDistributionType.InHouse;
            }
            else if (ProvisioningProfile == AutomaticAdHocProvision)
            {
                type = MobileProvisionDistributionType.AdHoc;
            }

            DetectedCodesignAllocate = Path.Combine(DeveloperRoot, "Toolchains", "XcodeDefault.xctoolchain", "usr", "bin", "codesign_allocate");
            DetectedDistributionType = type.ToString();

            identity.BundleId = BundleIdentifier;
            DetectedAppId     = BundleIdentifier;         // default value that can be changed below

            if (Platform == ApplePlatform.MacOSX)
            {
                if (!RequireCodeSigning || !string.IsNullOrEmpty(DetectedCodeSigningKey))
                {
                    ReportDetectedCodesignInfo();

                    return(!Log.HasLoggedErrors);
                }
            }
            else if (Platform == ApplePlatform.MacCatalyst)
            {
                var doesNotNeedCodeSigningCertificate = !RequireCodeSigning || !string.IsNullOrEmpty(DetectedCodeSigningKey);
                if (RequireProvisioningProfile)
                {
                    doesNotNeedCodeSigningCertificate = false;
                }
                if (doesNotNeedCodeSigningCertificate)
                {
                    DetectedCodeSigningKey = "-";

                    ReportDetectedCodesignInfo();

                    return(!Log.HasLoggedErrors);
                }
            }
            else
            {
                // Framework is either iOS, tvOS or watchOS
                if (SdkIsSimulator)
                {
                    if (AppleSdkSettings.XcodeVersion.Major >= 8 && RequireProvisioningProfile)
                    {
                        // Note: Starting with Xcode 8.0, we need to codesign iOS Simulator builds that enable Entitlements
                        // in order for them to run. The "-" key is a special value allowed by the codesign utility that
                        // allows us to get away with not having an actual codesign key.
                        DetectedCodeSigningKey = "-";

                        if (!IsAutoCodeSignProfile(ProvisioningProfile))
                        {
                            identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                            if (identity.Profile == null)
                            {
                                Log.LogError(MSBStrings.E0140, PlatformName, ProvisioningProfile);
                                return(false);
                            }

                            identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                            if (identity.AppId == null)
                            {
                                Log.LogError(MSBStrings.E0141, identity.BundleId, ProvisioningProfile);
                                return(false);
                            }

                            provisioningProfileName = identity.Profile.Name;

                            DetectedProvisioningProfile = identity.Profile.Uuid;
                            DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                        }
                        else
                        {
                            certs = new X509Certificate2[0];

                            if ((profiles = GetProvisioningProfiles(platform, type, identity, certs)) == null)
                            {
                                return(false);
                            }

                            if ((pairs = GetCodeSignIdentityPairs(profiles, certs)) == null)
                            {
                                return(false);
                            }

                            var match = GetBestMatch(pairs, identity);
                            identity.Profile = match.Profile;
                            identity.AppId   = match.AppId;

                            if (identity.Profile != null)
                            {
                                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                                DetectedProvisioningProfile = identity.Profile.Uuid;
                                provisioningProfileName     = identity.Profile.Name;
                            }

                            DetectedAppId = identity.AppId;
                        }
                    }
                    else
                    {
                        // Note: Do not codesign. Codesigning seems to break the iOS Simulator in older versions of Xcode.
                        DetectedCodeSigningKey = null;
                    }

                    ReportDetectedCodesignInfo();

                    return(!Log.HasLoggedErrors);
                }
            }

            // Note: if we make it this far, we absolutely need a codesigning certificate
            if (!TryGetSigningCertificates(out certs, false))
            {
                return(false);
            }

            Log.LogMessage(MessageImportance.Low, "Available certificates:");
            foreach (var cert in certs)
            {
                Log.LogMessage(MessageImportance.Low, "    {0}", SecKeychain.GetCertificateCommonName(cert));
            }

            if (!RequireProvisioningProfile)
            {
                if (certs.Count > 1)
                {
                    if (!string.IsNullOrEmpty(SigningKey))
                    {
                        Log.LogMessage(MessageImportance.Normal, MSBStrings.M0142, SigningKey);
                    }
                    else
                    {
                        Log.LogMessage(MessageImportance.Normal, MSBStrings.M0143);
                    }

                    for (int i = 0; i < certs.Count; i++)
                    {
                        Log.LogMessage(MessageImportance.Normal, "{0,3}. Signing Identity: {1} ({2})", i + 1,
                                       SecKeychain.GetCertificateCommonName(certs[i]), certs[i].Thumbprint);
                    }
                }

                codesignCommonName     = SecKeychain.GetCertificateCommonName(certs[0]);
                DetectedCodeSigningKey = certs[0].Thumbprint;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if (!IsAutoCodeSignProfile(ProvisioningProfile))
            {
                identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                if (identity.Profile == null)
                {
                    Log.LogError(MSBStrings.E0144, PlatformName, ProvisioningProfile);
                    return(false);
                }

                var profile = identity.Profile;                 // capture ref for lambda

                if (certs.Count > 0)
                {
                    identity.SigningKey = certs.FirstOrDefault(c => profile.DeveloperCertificates.Any(p => p.Thumbprint == c.Thumbprint));
                    if (identity.SigningKey == null)
                    {
                        Log.LogError(MSBStrings.E0145, PlatformName, ProvisioningProfile);
                        return(false);
                    }
                }

                identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                if (identity.AppId == null)
                {
                    Log.LogError(MSBStrings.E0141, identity.BundleId, ProvisioningProfile);
                    return(false);
                }

                if (identity.SigningKey != null)
                {
                    codesignCommonName     = SecKeychain.GetCertificateCommonName(identity.SigningKey);
                    DetectedCodeSigningKey = identity.SigningKey.Thumbprint;
                }

                provisioningProfileName = identity.Profile.Name;

                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if ((profiles = GetProvisioningProfiles(platform, type, identity, certs)) == null)
            {
                return(false);
            }

            if ((pairs = GetCodeSignIdentityPairs(profiles, certs)) == null)
            {
                return(false);
            }

            identity = GetBestMatch(pairs, identity);

            if (identity.Profile != null && identity.AppId != null)
            {
                codesignCommonName = identity.SigningKey != null?SecKeychain.GetCertificateCommonName(identity.SigningKey) : null;

                provisioningProfileName = identity.Profile.Name;

                DetectedCodeSigningKey      = identity.SigningKey?.Thumbprint;
                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();
            }
            else
            {
                if (identity.SigningKey != null)
                {
                    Log.LogError(MSBStrings.E0146, identity.BundleId, identity.SigningKey);
                }
                else
                {
                    Log.LogError(MSBStrings.E0148, identity.BundleId);
                }
            }

            return(!Log.HasLoggedErrors);
        }
示例#13
0
        public override bool Execute()
        {
            var type     = MobileProvisionDistributionType.Any;
            var identity = new CodeSignIdentity();
            MobileProvisionPlatform  platform;
            IList <MobileProvision>  profiles;
            IList <X509Certificate2> certs;
            PDictionary plist;

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            case "MacOSX":
                platform = MobileProvisionPlatform.MacOS;
                break;

            default:
                Log.LogError("Unknown SDK platform: {0}", SdkPlatform);
                return(false);
            }

            if (ProvisioningProfile == AutomaticAppStoreProvision)
            {
                type = MobileProvisionDistributionType.AppStore;
            }
            else if (ProvisioningProfile == AutomaticInHouseProvision)
            {
                type = MobileProvisionDistributionType.InHouse;
            }
            else if (ProvisioningProfile == AutomaticAdHocProvision)
            {
                type = MobileProvisionDistributionType.AdHoc;
            }

            try {
                plist = PDictionary.FromFile(AppManifest);
            } catch (Exception ex) {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Error loading '{0}': {1}", AppManifest, ex.Message);
                return(false);
            }

            DetectedCodesignAllocate = Path.Combine(DeveloperRoot, "Toolchains", "XcodeDefault.xctoolchain", "usr", "bin", "codesign_allocate");
            DetectedBundleVersion    = plist.GetCFBundleVersion();
            DetectedDistributionType = type.ToString();

            identity.BundleId = plist.GetCFBundleIdentifier();
            if (string.IsNullOrEmpty(identity.BundleId))
            {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "{0} does not define CFBundleIdentifier", AppManifest);
                return(false);
            }

            if (Framework == PlatformFramework.MacOS && !RequireCodeSigning)
            {
                DetectedBundleId = identity.BundleId;
                DetectedAppId    = DetectedBundleId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if (!RequireProvisioningProfile && string.IsNullOrEmpty(ProvisioningProfile))
            {
                if (SdkIsSimulator && AppleSdkSettings.XcodeVersion.Major >= 8)
                {
                    // Note: Starting with Xcode 8.0, we need to codesign iOS Simulator builds in order for them to run.
                    // The "-" key is a special value allowed by the codesign utility that allows us to get away with
                    // not having an actual codesign key. As far as we know, this only works with Xcode >= 8.
                    DetectedCodeSigningKey = "-";
                }
                else
                {
                    // Try and get a valid codesigning certificate...
                    if (!TryGetSigningCertificates(out certs, SdkIsSimulator))
                    {
                        return(false);
                    }

                    if (certs.Count > 0)
                    {
                        if (certs.Count > 1)
                        {
                            if (!string.IsNullOrEmpty(SigningKey))
                            {
                                Log.LogMessage(MessageImportance.Normal, "Multiple signing identities match '{0}'; using the first match.", SigningKey);
                            }
                            else
                            {
                                Log.LogMessage(MessageImportance.Normal, "Multiple signing identities found; using the first identity.");
                            }

                            for (int i = 0; i < certs.Count; i++)
                            {
                                Log.LogMessage(MessageImportance.Normal, "{0,3}. Signing Identity: {1} ({2})", i + 1,
                                               SecKeychain.GetCertificateCommonName(certs[i]), certs[i].Thumbprint);
                            }
                        }

                        codesignCommonName     = SecKeychain.GetCertificateCommonName(certs[0]);
                        DetectedCodeSigningKey = certs[0].Thumbprint;
                    }
                    else
                    {
                        // Note: We don't have to codesign for iOS Simulator builds meant to run on Xcode iOS Simulators
                        // older than 8.0, so it's non-fatal if we don't find any...
                    }
                }

                DetectedBundleId = identity.BundleId;
                DetectedAppId    = DetectedBundleId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            // Note: if we make it this far, we absolutely need a codesigning certificate
            if (!TryGetSigningCertificates(out certs, false))
            {
                return(false);
            }

            if (certs.Count > 0)
            {
                Log.LogMessage(MessageImportance.Low, "Available certificates:");
                foreach (var cert in certs)
                {
                    Log.LogMessage(MessageImportance.Low, "    {0}", Xamarin.MacDev.Keychain.GetCertificateCommonName(cert));
                }
            }

            if (!IsAutoCodeSignProfile(ProvisioningProfile))
            {
                identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                if (identity.Profile == null)
                {
                    Log.LogError("The specified " + PlatformName + " provisioning profile '{0}' could not be found", ProvisioningProfile);
                    return(false);
                }

                var profile = identity.Profile;                 // capture ref for lambda

                if (certs.Count > 0)
                {
                    identity.SigningKey = certs.FirstOrDefault(c => profile.DeveloperCertificates.Any(p => p.Thumbprint == c.Thumbprint));
                    if (identity.SigningKey == null)
                    {
                        Log.LogError("No " + PlatformName + " signing identities match the specified provisioning profile '{0}'.", ProvisioningProfile);
                        return(false);
                    }
                }

                identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                if (identity.AppId == null)
                {
                    Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'", identity.BundleId, ProvisioningProfile);
                    return(false);
                }

                if (identity.SigningKey != null)
                {
                    codesignCommonName     = SecKeychain.GetCertificateCommonName(identity.SigningKey);
                    DetectedCodeSigningKey = identity.SigningKey.Thumbprint;
                }

                provisioningProfileName = identity.Profile.Name;

                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            List <string> failures = new List <string> ();

            if (identity.BundleId != null)
            {
                if (certs.Count > 0)
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type, certs, unique: true, failures: failures);
                }
                else
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type, unique: true, failures: failures);
                }
            }
            else if (certs.Count > 0)
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type, certs, unique: true, failures: failures);
            }
            else
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type, unique: true, failures: failures);
            }

            if (profiles.Count == 0)
            {
                foreach (var f in failures)
                {
                    Log.LogMessage(MessageImportance.Low, "{0}", f);
                }
                Log.LogError($"Could not find any available provisioning profiles for {PlatformName}.");
                return(false);
            }
            else
            {
                Log.LogMessage(MessageImportance.Low, "Available profiles:");
                foreach (var p in profiles)
                {
                    Log.LogMessage(MessageImportance.Low, "    {0}", p.Name);
                }
            }

            List <CodeSignIdentity> pairs;

            if (certs.Count > 0)
            {
                pairs = (from p in profiles
                         from c in certs
                         where p.DeveloperCertificates.Any(d => d.Thumbprint == c.Thumbprint)
                         select new CodeSignIdentity {
                    SigningKey = c, Profile = p
                }).ToList();

                if (pairs.Count == 0)
                {
                    Log.LogError("No installed provisioning profiles match the installed " + PlatformName + " signing identities.");
                    return(false);
                }
            }
            else
            {
                pairs = (from p in profiles select new CodeSignIdentity {
                    Profile = p
                }).ToList();
            }

            var matches         = new List <CodeSignIdentity> ();
            int bestMatchLength = 0;
            int matchLength;

            // find matching provisioning profiles with compatible appid, keeping only those with the longest matching (wildcard) ids
            foreach (var pair in pairs)
            {
                var appid = ConstructValidAppId(pair.Profile, identity.BundleId, out matchLength);
                if (appid != null && matchLength >= bestMatchLength)
                {
                    if (matchLength > bestMatchLength)
                    {
                        bestMatchLength = matchLength;
                        matches.Clear();
                    }

                    var match = identity.Clone();
                    match.SigningKey = pair.SigningKey;
                    match.Profile    = pair.Profile;
                    match.AppId      = appid;

                    matches.Add(match);
                }
            }

            if (matches.Count == 0)
            {
                Log.LogWarning(null, null, null, AppManifest, 0, 0, 0, 0, "No installed provisioning profiles match the bundle identifier.");
            }
            else
            {
                if (matches.Count > 1)
                {
                    var spaces = new string (' ', 3);

                    Log.LogMessage(MessageImportance.Normal, "Multiple provisioning profiles match the bundle identifier; using the first match.");

                    matches.Sort(new SigningIdentityComparer());

                    for (int i = 0; i < matches.Count; i++)
                    {
                        Log.LogMessage(MessageImportance.Normal, "{0,3}. Provisioning Profile: \"{1}\" ({2})", i + 1, matches[i].Profile.Name, matches[i].Profile.Uuid);

                        if (matches[i].SigningKey != null)
                        {
                            Log.LogMessage(MessageImportance.Normal, "{0}  Signing Identity: \"{1}\"", spaces, SecKeychain.GetCertificateCommonName(matches[i].SigningKey));
                        }
                    }
                }

                identity = matches[0];
            }

            if (identity.Profile != null && identity.AppId != null)
            {
                codesignCommonName = identity.SigningKey != null?SecKeychain.GetCertificateCommonName(identity.SigningKey) : null;

                provisioningProfileName = identity.Profile.Name;

                DetectedCodeSigningKey      = identity.SigningKey?.Thumbprint;
                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();
            }
            else
            {
                if (identity.SigningKey != null)
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'.", identity.BundleId, identity.SigningKey);
                }
                else
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile.", identity.BundleId);
                }
            }

            return(!Log.HasLoggedErrors);
        }
示例#14
0
        public override bool Execute()
        {
            var type     = MobileProvisionDistributionType.Any;
            var identity = new CodeSignIdentity();
            MobileProvisionPlatform  platform;
            IList <MobileProvision>  profiles;
            IList <X509Certificate2> certs;
            List <CodeSignIdentity>  pairs;
            PDictionary plist;

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            case "MacOSX":
                platform = MobileProvisionPlatform.MacOS;
                break;

            default:
                Log.LogError("Unknown SDK platform: {0}", SdkPlatform);
                return(false);
            }

            if (ProvisioningProfile == AutomaticAppStoreProvision)
            {
                type = MobileProvisionDistributionType.AppStore;
            }
            else if (ProvisioningProfile == AutomaticInHouseProvision)
            {
                type = MobileProvisionDistributionType.InHouse;
            }
            else if (ProvisioningProfile == AutomaticAdHocProvision)
            {
                type = MobileProvisionDistributionType.AdHoc;
            }

            try {
                plist = PDictionary.FromFile(AppManifest);
            } catch (Exception ex) {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Error loading '{0}': {1}", AppManifest, ex.Message);
                return(false);
            }

            DetectedCodesignAllocate = Path.Combine(DeveloperRoot, "Toolchains", "XcodeDefault.xctoolchain", "usr", "bin", "codesign_allocate");
            DetectedBundleVersion    = plist.GetCFBundleVersion();
            DetectedDistributionType = type.ToString();

            identity.BundleId = plist.GetCFBundleIdentifier();
            if (string.IsNullOrEmpty(identity.BundleId))
            {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "{0} does not define CFBundleIdentifier", AppManifest);
                return(false);
            }

            if (Framework == PlatformFramework.MacOS)
            {
                if (!RequireCodeSigning)
                {
                    DetectedBundleId = identity.BundleId;
                    DetectedAppId    = DetectedBundleId;

                    ReportDetectedCodesignInfo();

                    return(!Log.HasLoggedErrors);
                }
            }
            else
            {
                // Framework is either iOS, tvOS or watchOS
                if (SdkIsSimulator)
                {
                    if (AppleSdkSettings.XcodeVersion.Major >= 8 && RequireProvisioningProfile)
                    {
                        // Note: Starting with Xcode 8.0, we need to codesign iOS Simulator builds that enable Entitlements
                        // in order for them to run. The "-" key is a special value allowed by the codesign utility that
                        // allows us to get away with not having an actual codesign key.
                        DetectedCodeSigningKey = "-";

                        if (!IsAutoCodeSignProfile(ProvisioningProfile))
                        {
                            identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                            if (identity.Profile == null)
                            {
                                Log.LogError("The specified " + PlatformName + " provisioning profile '{0}' could not be found", ProvisioningProfile);
                                return(false);
                            }

                            identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                            if (identity.AppId == null)
                            {
                                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'", identity.BundleId, ProvisioningProfile);
                                return(false);
                            }

                            provisioningProfileName = identity.Profile.Name;

                            DetectedProvisioningProfile = identity.Profile.Uuid;
                            DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                            DetectedBundleId            = identity.BundleId;
                            DetectedAppId = DetectedBundleId;
                        }
                        else
                        {
                            certs = new X509Certificate2[0];

                            if ((profiles = GetProvisioningProfiles(platform, type, identity, certs)) == null)
                            {
                                return(false);
                            }

                            if ((pairs = GetCodeSignIdentityPairs(profiles, certs)) == null)
                            {
                                return(false);
                            }

                            var match = GetBestMatch(pairs, identity);
                            identity.Profile = match.Profile;
                            identity.AppId   = match.AppId;

                            if (identity.Profile != null)
                            {
                                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                                DetectedProvisioningProfile = identity.Profile.Uuid;
                                provisioningProfileName     = identity.Profile.Name;
                            }

                            DetectedBundleId = identity.BundleId;
                            DetectedAppId    = identity.AppId;
                        }
                    }
                    else
                    {
                        // Note: Do not codesign. Codesigning seems to break the iOS Simulator in older versions of Xcode.
                        DetectedCodeSigningKey = null;

                        DetectedBundleId = identity.BundleId;
                        DetectedAppId    = DetectedBundleId;
                    }

                    ReportDetectedCodesignInfo();

                    return(!Log.HasLoggedErrors);
                }
            }

            // Note: if we make it this far, we absolutely need a codesigning certificate
            if (!TryGetSigningCertificates(out certs, false))
            {
                return(false);
            }

            Log.LogMessage(MessageImportance.Low, "Available certificates:");
            foreach (var cert in certs)
            {
                Log.LogMessage(MessageImportance.Low, "    {0}", SecKeychain.GetCertificateCommonName(cert));
            }

            if (!RequireProvisioningProfile)
            {
                if (certs.Count > 1)
                {
                    if (!string.IsNullOrEmpty(SigningKey))
                    {
                        Log.LogMessage(MessageImportance.Normal, "Multiple signing identities match '{0}'; using the first match.", SigningKey);
                    }
                    else
                    {
                        Log.LogMessage(MessageImportance.Normal, "Multiple signing identities found; using the first identity.");
                    }

                    for (int i = 0; i < certs.Count; i++)
                    {
                        Log.LogMessage(MessageImportance.Normal, "{0,3}. Signing Identity: {1} ({2})", i + 1,
                                       SecKeychain.GetCertificateCommonName(certs[i]), certs[i].Thumbprint);
                    }
                }

                codesignCommonName     = SecKeychain.GetCertificateCommonName(certs[0]);
                DetectedCodeSigningKey = certs[0].Thumbprint;
                DetectedBundleId       = identity.BundleId;
                DetectedAppId          = DetectedBundleId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if (!IsAutoCodeSignProfile(ProvisioningProfile))
            {
                identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                if (identity.Profile == null)
                {
                    Log.LogError("The specified " + PlatformName + " provisioning profile '{0}' could not be found", ProvisioningProfile);
                    return(false);
                }

                var profile = identity.Profile;                 // capture ref for lambda

                if (certs.Count > 0)
                {
                    identity.SigningKey = certs.FirstOrDefault(c => profile.DeveloperCertificates.Any(p => p.Thumbprint == c.Thumbprint));
                    if (identity.SigningKey == null)
                    {
                        Log.LogError("No " + PlatformName + " signing identities match the specified provisioning profile '{0}'.", ProvisioningProfile);
                        return(false);
                    }
                }

                identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                if (identity.AppId == null)
                {
                    Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'", identity.BundleId, ProvisioningProfile);
                    return(false);
                }

                if (identity.SigningKey != null)
                {
                    codesignCommonName     = SecKeychain.GetCertificateCommonName(identity.SigningKey);
                    DetectedCodeSigningKey = identity.SigningKey.Thumbprint;
                }

                provisioningProfileName = identity.Profile.Name;

                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if ((profiles = GetProvisioningProfiles(platform, type, identity, certs)) == null)
            {
                return(false);
            }

            if ((pairs = GetCodeSignIdentityPairs(profiles, certs)) == null)
            {
                return(false);
            }

            identity = GetBestMatch(pairs, identity);

            if (identity.Profile != null && identity.AppId != null)
            {
                codesignCommonName = identity.SigningKey != null?SecKeychain.GetCertificateCommonName(identity.SigningKey) : null;

                provisioningProfileName = identity.Profile.Name;

                DetectedCodeSigningKey      = identity.SigningKey?.Thumbprint;
                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();
            }
            else
            {
                if (identity.SigningKey != null)
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'.", identity.BundleId, identity.SigningKey);
                }
                else
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile.", identity.BundleId);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var type     = MobileProvisionDistributionType.Any;
            var identity = new CodeSignIdentity();
            MobileProvisionPlatform  platform;
            IList <MobileProvision>  profiles;
            IList <X509Certificate2> certs;
            PDictionary plist;

            Log.LogTaskName("DetectSigningIdentity");
            Log.LogTaskProperty("AppBundleName", AppBundleName);
            Log.LogTaskProperty("AppManifest", AppManifest);
            Log.LogTaskProperty("Keychain", Keychain);
            Log.LogTaskProperty("ProvisioningProfile", ProvisioningProfile);
            Log.LogTaskProperty("RequireCodesigning", RequireCodeSigning);
            Log.LogTaskProperty("RequireProvisioningProfile", RequireProvisioningProfile);
            Log.LogTaskProperty("SdkPlatform", SdkPlatform);
            Log.LogTaskProperty("SdkIsSimulator", SdkIsSimulator);
            Log.LogTaskProperty("SigningKey", SigningKey);

            switch (SdkPlatform)
            {
            case "AppleTVSimulator":
            case "AppleTVOS":
                platform = MobileProvisionPlatform.tvOS;
                break;

            case "iPhoneSimulator":
            case "WatchSimulator":
            case "iPhoneOS":
            case "WatchOS":
                platform = MobileProvisionPlatform.iOS;
                break;

            case "MacOSX":
                platform = MobileProvisionPlatform.MacOS;
                break;

            default:
                Log.LogError("Unknown SDK platform: {0}", SdkPlatform);
                return(false);
            }

            if (ProvisioningProfile == AutomaticAppStoreProvision)
            {
                type = MobileProvisionDistributionType.AppStore;
            }
            else if (ProvisioningProfile == AutomaticInHouseProvision)
            {
                type = MobileProvisionDistributionType.InHouse;
            }
            else if (ProvisioningProfile == AutomaticAdHocProvision)
            {
                type = MobileProvisionDistributionType.AdHoc;
            }

            try {
                plist = PDictionary.FromFile(AppManifest);
            } catch (Exception ex) {
                Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Error loading '{0}': {1}", AppManifest, ex.Message);
                return(false);
            }

            DetectedCodesignAllocate = Path.Combine(DeveloperRoot, "Toolchains", "XcodeDefault.xctoolchain", "usr", "bin", "codesign_allocate");
            DetectedBundleVersion    = plist.GetCFBundleVersion();
            DetectedDistributionType = type.ToString();

            identity.BundleId = plist.GetCFBundleIdentifier();
            if (string.IsNullOrEmpty(identity.BundleId))
            {
                identity.BundleId = null;
            }

            if (Framework == PlatformFramework.MacOS && !RequireCodeSigning)
            {
                DetectedBundleId = identity.BundleId ?? GetDefaultBundleId(AppBundleName, null);
                DetectedAppId    = DetectedBundleId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            try {
                var keychain = !string.IsNullOrEmpty(Keychain) ? SecKeychain.Open(Keychain) : SecKeychain.Default;

                if (string.IsNullOrEmpty(SigningKey) || MatchesAny(SigningKey, DevelopmentPrefixes))
                {
                    // Note: we treat an empty signing key as "developer automatic".
                    if (!TryGetSigningCertificates(keychain, out certs, DevelopmentPrefixes))
                    {
                        return(false);
                    }
                }
                else if (MatchesAny(SigningKey, AppStoreDistributionPrefixes))
                {
                    if (!TryGetSigningCertificates(keychain, out certs, AppStoreDistributionPrefixes))
                    {
                        return(false);
                    }
                }
                else if (MatchesAny(SigningKey, DirectDistributionPrefixes))
                {
                    if (!TryGetSigningCertificates(keychain, out certs, DirectDistributionPrefixes))
                    {
                        return(false);
                    }
                }
                else
                {
                    // The user has specified an exact name to match...
                    if (!TryGetSigningCertificates(keychain, out certs, SigningKey))
                    {
                        return(false);
                    }
                }
            } catch (Exception ex) {
                Log.LogError("{0}", ex.Message);
                return(false);
            }

            if (!RequireProvisioningProfile && string.IsNullOrEmpty(ProvisioningProfile))
            {
                if (certs.Count > 1)
                {
                    if (!string.IsNullOrEmpty(SigningKey))
                    {
                        Log.LogMessage(MessageImportance.Normal, "Multiple signing identities match '{0}'; using the first match.", SigningKey);
                    }
                    else
                    {
                        Log.LogMessage(MessageImportance.Normal, "Multiple signing identities found; using the first identity.");
                    }

                    for (int i = 0; i < certs.Count; i++)
                    {
                        Log.LogMessage(MessageImportance.Normal, "{0,3}. Signing Identity: {1} ({2})", i + 1,
                                       SecKeychain.GetCertificateCommonName(certs[i]), certs[i].Thumbprint);
                    }
                }

                codesignCommonName     = SecKeychain.GetCertificateCommonName(certs[0]);
                DetectedCodeSigningKey = certs[0].Thumbprint;

                DetectedBundleId = identity.BundleId ?? GetDefaultBundleId(AppBundleName, null);
                DetectedAppId    = DetectedBundleId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if (!IsAutoCodeSignProfile(ProvisioningProfile))
            {
                identity.Profile = MobileProvisionIndex.GetMobileProvision(platform, ProvisioningProfile);

                if (identity.Profile == null)
                {
                    Log.LogError("The specified " + PlatformName + " provisioning profile '{0}' could not be found", ProvisioningProfile);
                    return(false);
                }

                var profile = identity.Profile;                 // capture ref for lambda

                if (certs.Count > 0)
                {
                    identity.SigningKey = certs.FirstOrDefault(c => profile.DeveloperCertificates.Any(p => p.Thumbprint == c.Thumbprint));
                    if (identity.SigningKey == null)
                    {
                        Log.LogError("No " + PlatformName + " signing identities match the specified provisioning profile '{0}'.", ProvisioningProfile);
                        return(false);
                    }
                }

                if (identity.BundleId == null)
                {
                    identity.BundleId = GetDefaultBundleId(AppBundleName, GetProfileBundleId(identity.Profile));
                    Log.LogWarning(null, null, null, AppManifest, 0, 0, 0, 0, "Project does not have bundle identifier specified. Using '{0}' to match provisioning profile.", identity.BundleId);
                }

                identity.AppId = ConstructValidAppId(identity.Profile, identity.BundleId);
                if (identity.AppId == null)
                {
                    Log.LogError(null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'", identity.BundleId, ProvisioningProfile);
                    return(false);
                }

                if (identity.SigningKey != null)
                {
                    codesignCommonName     = SecKeychain.GetCertificateCommonName(identity.SigningKey);
                    DetectedCodeSigningKey = identity.SigningKey.Thumbprint;
                }

                provisioningProfileName = identity.Profile.Name;

                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedDistributionType    = identity.Profile.DistributionType.ToString();
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();

                return(!Log.HasLoggedErrors);
            }

            if (identity.BundleId != null)
            {
                if (certs.Count > 0)
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type, certs);
                }
                else
                {
                    profiles = MobileProvisionIndex.GetMobileProvisions(platform, identity.BundleId, type);
                }
            }
            else if (certs.Count > 0)
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type, certs);
            }
            else
            {
                profiles = MobileProvisionIndex.GetMobileProvisions(platform, type);
            }

            List <CodeSignIdentity> pairs;

            if (certs.Count > 0)
            {
                pairs = (from p in profiles
                         from c in certs
                         where p.DeveloperCertificates.Any(d => d.Thumbprint == c.Thumbprint)
                         select new CodeSignIdentity {
                    SigningKey = c, Profile = p
                }).ToList();

                if (pairs.Count == 0)
                {
                    Log.LogError("No installed provisioning profiles match the installed " + PlatformName + " signing identities.");
                    return(false);
                }
            }
            else
            {
                pairs = (from p in profiles select new CodeSignIdentity {
                    Profile = p
                }).ToList();
            }

            if (identity.BundleId != null)
            {
                var matches         = new List <CodeSignIdentity> ();
                int bestMatchLength = 0;
                int matchLength;

                // find matching provisioning profiles with compatible appid, keeping only those with the longest matching (wildcard) ids
                foreach (var pair in pairs)
                {
                    var appid = ConstructValidAppId(pair.Profile, identity.BundleId, out matchLength);
                    if (appid != null && matchLength >= bestMatchLength)
                    {
                        if (matchLength > bestMatchLength)
                        {
                            bestMatchLength = matchLength;
                            matches.Clear();
                        }

                        var match = identity.Clone();
                        match.SigningKey = pair.SigningKey;
                        match.Profile    = pair.Profile;
                        match.AppId      = appid;

                        matches.Add(match);
                    }
                }

                if (matches.Count == 0)
                {
                    Log.LogWarning(null, null, null, AppManifest, 0, 0, 0, 0, "No installed provisioning profiles match the bundle identifier.");
                }
                else
                {
                    if (matches.Count > 1)
                    {
                        var spaces = new string (' ', 3);

                        Log.LogMessage(MessageImportance.Normal, "Multiple provisioning profiles match the bundle identifier; using the first match.");

                        matches.Sort(new SigningIdentityComparer());

                        for (int i = 0; i < matches.Count; i++)
                        {
                            Log.LogMessage(MessageImportance.Normal, "{0,3}. Provisioning Profile: \"{1}\" ({2})", i + 1, matches[i].Profile.Name, matches[i].Profile.Uuid);

                            if (matches[i].SigningKey != null)
                            {
                                Log.LogMessage(MessageImportance.Normal, "{0}  Signing Identity: \"{1}\"", spaces, SecKeychain.GetCertificateCommonName(matches[i].SigningKey));
                            }
                        }
                    }

                    identity = matches[0];
                }
            }
            else
            {
                // pick a provisioning profile to provide appid and better default bundle identifier, preferring wildcard bundle identifiers
                foreach (var pair in pairs)
                {
                    var  suggestion = GetProfileBundleId(pair.Profile);
                    bool wildcard   = (suggestion != null) && suggestion.EndsWith("*", StringComparison.Ordinal);

                    if (wildcard || identity.Profile == null)
                    {
                        identity.Profile    = pair.Profile;
                        identity.SigningKey = pair.SigningKey;
                        identity.BundleId   = GetDefaultBundleId(AppBundleName, suggestion);
                        identity.AppId      = ConstructValidAppId(pair.Profile, identity.BundleId);
                    }

                    if (wildcard)
                    {
                        break;
                    }
                }

                Log.LogWarning(null, null, null, AppManifest, 0, 0, 0, 0, "No bundle identifier specified. Using '{0}' to match an installed provisioning profile.", identity.BundleId);
            }

            if (identity.Profile != null && identity.AppId != null)
            {
                codesignCommonName = identity.SigningKey != null?SecKeychain.GetCertificateCommonName(identity.SigningKey) : null;

                provisioningProfileName = identity.Profile.Name;

                DetectedCodeSigningKey      = identity.SigningKey?.Thumbprint;
                DetectedProvisioningProfile = identity.Profile.Uuid;
                DetectedBundleId            = identity.BundleId;
                DetectedAppId = identity.AppId;

                ReportDetectedCodesignInfo();
            }
            else
            {
                if (identity.SigningKey != null)
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'.", identity.BundleId, identity.SigningKey);
                }
                else
                {
                    Log.LogError("Bundle identifier '{0}' does not match any installed provisioning profile.", identity.BundleId);
                }
            }

            return(!Log.HasLoggedErrors);
        }