Exemple #1
0
        public static string FindCompatibleProvision(string CFBundleIdentifier, out bool bNameMatch, bool bCheckCert = true, bool bCheckIdentifier = true, bool bCheckDistro = true)
        {
            bNameMatch = false;

            // remap the gamename if necessary
            string GameName = Program.GameName;

            if (GameName == "UE4Game")
            {
                if (Config.ProjectFile.Length > 0)
                {
                    GameName = Path.GetFileNameWithoutExtension(Config.ProjectFile);
                }
            }

            // ensure the provision directory exists
            if (!Directory.Exists(Config.ProvisionDirectory))
            {
                Directory.CreateDirectory(Config.ProvisionDirectory);
            }

            if (Config.bProvision)
            {
                if (File.Exists(Config.ProvisionDirectory + "/" + Config.Provision))
                {
                    return(Config.ProvisionDirectory + "/" + Config.Provision);
                }
            }

            #region remove after we provide an install mechanism
            CacheMobileProvisions();
            #endregion

            // cache the provision library
            Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>();
            foreach (string Provision in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision"))
            {
                MobileProvision p = MobileProvisionParser.ParseFile(Provision);
                ProvisionLibrary.Add(Provision, p);
                if (p.FileName.Contains(p.UUID) && !File.Exists(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision")))
                {
                    File.Copy(Provision, Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision"));
                    p = MobileProvisionParser.ParseFile(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision"));
                    ProvisionLibrary.Add(Path.Combine(Config.ProvisionDirectory, "UE4_" + p.UUID + ".mobileprovision"), p);
                }
            }

            Program.Log("Searching for mobile provisions that match the game '{0}' (distribution: {3}) with CFBundleIdentifier='{1}' in '{2}'", GameName, CFBundleIdentifier, Config.ProvisionDirectory, Config.bForDistribution);

            // check the cache for a provision matching the app id (com.company.Game)
            // First checking for a contains match and then for a wildcard match
            for (int Phase = -1; Phase < 3; ++Phase)
            {
                if (Phase == -1 && string.IsNullOrEmpty(Config.ProvisionUUID))
                {
                    continue;
                }
                foreach (KeyValuePair <string, MobileProvision> Pair in ProvisionLibrary)
                {
                    string          DebugName     = Path.GetFileName(Pair.Key);
                    MobileProvision TestProvision = Pair.Value;

                    // make sure the file is not managed by Xcode
                    if (Path.GetFileName(TestProvision.FileName).ToLower().Equals(TestProvision.UUID.ToLower() + ".mobileprovision"))
                    {
                        continue;
                    }

                    Program.LogVerbose("  Phase {0} considering provision '{1}' named '{2}'", Phase, DebugName, TestProvision.ProvisionName);

                    if (TestProvision.ProvisionName == "iOS Team Provisioning Profile: " + CFBundleIdentifier)
                    {
                        Program.LogVerbose("  Failing as provisioning is automatic");
                        continue;
                    }

                    // check to see if the platform is the same as what we are looking for
                    if (!string.IsNullOrEmpty(TestProvision.Platform) && TestProvision.Platform != Config.OSString && !string.IsNullOrEmpty(Config.OSString))
                    {
                        //Program.LogVerbose("  Failing platform {0} Config: {1}", TestProvision.Platform, Config.OSString);
                        continue;
                    }

                    // Validate the name
                    bool bPassesNameCheck = false;
                    if (Phase == -1)
                    {
                        bPassesNameCheck = TestProvision.UUID == Config.ProvisionUUID;
                        bNameMatch       = bPassesNameCheck;
                    }
                    else if (Phase == 0)
                    {
                        bPassesNameCheck = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier;
                        bNameMatch       = bPassesNameCheck;
                    }
                    else if (Phase == 1)
                    {
                        if (TestProvision.ApplicationIdentifier.Contains("*"))
                        {
                            string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1);
                            if (CompanyName != "*")
                            {
                                CompanyName      = CompanyName.Substring(0, CompanyName.LastIndexOf("."));
                                bPassesNameCheck = CFBundleIdentifier.StartsWith(CompanyName);
                            }
                        }
                    }
                    else
                    {
                        if (TestProvision.ApplicationIdentifier.Contains("*"))
                        {
                            string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1);
                            bPassesNameCheck = CompanyName == "*";
                        }
                    }
                    if (!bPassesNameCheck && bCheckIdentifier)
                    {
                        Program.LogVerbose("  .. Failed phase {0} name check (provision app ID was {1})", Phase, TestProvision.ApplicationIdentifier);
                        continue;
                    }

                    if (Config.bForDistribution)
                    {
                        // Check to see if this is a distribution provision. get-task-allow must be false for distro profiles.
                        // TestProvision.ProvisionedDeviceIDs.Count==0 is not a valid check as ad-hoc distro profiles do list devices.
                        bool bDistroProv = !TestProvision.bDebug;
                        if (!bDistroProv)
                        {
                            Program.LogVerbose("  .. Failed distribution check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count);
                            continue;
                        }
                    }
                    else
                    {
                        if (bCheckDistro)
                        {
                            bool bPassesDebugCheck = TestProvision.bDebug;
                            if (!bPassesDebugCheck)
                            {
                                Program.LogVerbose("  .. Failed debugging check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count);
                                continue;
                            }
                        }
                        else
                        {
                            if (!TestProvision.bDebug)
                            {
                                Config.bForceStripSymbols = true;
                            }
                        }
                    }

                    // Check to see if the provision is in date
                    DateTime CurrentUTCTime   = DateTime.UtcNow;
                    bool     bPassesDateCheck = (CurrentUTCTime >= TestProvision.CreationDate) && (CurrentUTCTime < TestProvision.ExpirationDate);
                    if (!bPassesDateCheck)
                    {
                        Program.LogVerbose("  .. Failed time period check (valid from {0} to {1}, but UTC time is now {2})", TestProvision.CreationDate, TestProvision.ExpirationDate, CurrentUTCTime);
                        continue;
                    }

                    // check to see if we have a certificate for this provision
                    bool bPassesHasMatchingCertCheck = false;
                    if (bCheckCert)
                    {
                        X509Certificate2 Cert = CodeSignatureBuilder.FindCertificate(TestProvision);
                        bPassesHasMatchingCertCheck = (Cert != null);
                        if (bPassesHasMatchingCertCheck && Config.bCert)
                        {
                            bPassesHasMatchingCertCheck &= (CryptoAdapter.GetFriendlyNameFromCert(Cert) == Config.Certificate);
                        }
                    }
                    else
                    {
                        bPassesHasMatchingCertCheck = true;
                    }

                    if (!bPassesHasMatchingCertCheck)
                    {
                        Program.LogVerbose("  .. Failed to find a matching certificate that was in date");
                        continue;
                    }

                    // Made it past all the tests
                    Program.LogVerbose("  Picked '{0}' with AppID '{1}' and Name '{2}' as a matching provision for the game '{3}'", DebugName, TestProvision.ApplicationIdentifier, TestProvision.ProvisionName, GameName);
                    return(Pair.Key);
                }
            }

            // check to see if there is already an embedded provision
            string EmbeddedMobileProvisionFilename = Path.Combine(Config.RepackageStagingDirectory, "embedded.mobileprovision");

            Program.Warning("Failed to find a valid matching mobile provision, will attempt to use the embedded mobile provision instead if present");
            return(EmbeddedMobileProvisionFilename);
        }
Exemple #2
0
        /// <summary>
        /// Tries to find a matching certificate on this machine from the the serial number of one of the
        /// certificates in the mobile provision (the one in the mobileprovision is missing the public/private key pair)
        /// </summary>
        public static X509Certificate2 FindCertificate(MobileProvision ProvisionToWorkFrom)
        {
            Program.LogVerbose("  Looking for a certificate that matches the application identifier '{0}'", ProvisionToWorkFrom.ApplicationIdentifier);

            X509Certificate2 Result = null;

            if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
            {
                // run certtool y to get the currently installed certificates
                CertToolData = "";
                Process CertTool = new Process();
                CertTool.StartInfo.FileName               = "/usr/bin/security";
                CertTool.StartInfo.UseShellExecute        = false;
                CertTool.StartInfo.Arguments              = "find-identity -p codesigning -v";
                CertTool.StartInfo.RedirectStandardOutput = true;
                CertTool.OutputDataReceived              += new DataReceivedEventHandler(OutputReceivedCertToolProcessCall);
                CertTool.Start();
                CertTool.BeginOutputReadLine();
                CertTool.WaitForExit();
                if (CertTool.ExitCode == 0)
                {
                    foreach (X509Certificate2 SourceCert in ProvisionToWorkFrom.DeveloperCertificates)
                    {
                        X509Certificate2 ValidInTimeCert = null;
                        // see if certificate can be found by serial number
                        string CertHash = SourceCert.GetCertHashString();

                        if (CertToolData.Contains(CertHash))
                        {
                            ValidInTimeCert = SourceCert;
                        }

                        if (ValidInTimeCert != null)
                        {
                            int StartIndex = SourceCert.SubjectName.Name.IndexOf("CN=") + 3;
                            int EndIndex   = SourceCert.SubjectName.Name.IndexOf(", ", StartIndex);
                            SourceCert.FriendlyName = SourceCert.SubjectName.Name.Substring(StartIndex, EndIndex - StartIndex);

                            // Found a cert in the valid time range, quit now!
                            Result = ValidInTimeCert;
                            break;
                        }
                    }
                }
            }
            else
            {
                // Open the personal certificate store on this machine
                X509Store Store = new X509Store();
                Store.Open(OpenFlags.ReadOnly);

                // Try finding a matching certificate from the serial number (the one in the mobileprovision is missing the public/private key pair)
                foreach (X509Certificate2 SourceCert in ProvisionToWorkFrom.DeveloperCertificates)
                {
                    X509Certificate2Collection FoundCerts = Store.Certificates.Find(X509FindType.FindBySerialNumber, SourceCert.SerialNumber, false);

                    Program.LogVerbose("  .. Provision entry SN '{0}' matched {1} installed certificate(s)", SourceCert.SerialNumber, FoundCerts.Count);

                    X509Certificate2 ValidInTimeCert = null;
                    foreach (X509Certificate2 TestCert in FoundCerts)
                    {
                        //@TODO: Pretty sure the certificate information from the library is in local time, not UTC and this works as expected, but it should be verified!
                        DateTime EffectiveDate  = TestCert.NotBefore;
                        DateTime ExpirationDate = TestCert.NotAfter;
                        DateTime Now            = DateTime.Now;

                        bool bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);

                        Program.LogVerbose("  .. .. Installed certificate '{0}' is {1} (range '{2}' to '{3}')", TestCert.FriendlyName, bCertTimeIsValid ? "valid (choosing it)" : "EXPIRED", TestCert.GetEffectiveDateString(), TestCert.GetExpirationDateString());
                        if (bCertTimeIsValid)
                        {
                            ValidInTimeCert = TestCert;
                            break;
                        }
                    }

                    if (ValidInTimeCert != null)
                    {
                        // Found a cert in the valid time range, quit now!
                        Result = ValidInTimeCert;
                        break;
                    }
                }

                Store.Close();
            }

            if (Result == null)
            {
                Program.LogVerbose("  .. Failed to find a valid certificate that was in date");
            }

            return(Result);
        }
Exemple #3
0
        public static string FindCompatibleProvision(string CFBundleIdentifier, out bool bNameMatch, bool bCheckCert = true, bool bCheckIdentifier = true)
        {
            bNameMatch = false;

            // remap the gamename if necessary
            string GameName = Program.GameName;

            if (GameName == "UE4Game")
            {
                if (Config.ProjectFile.Length > 0)
                {
                    GameName = Path.GetFileNameWithoutExtension(Config.ProjectFile);
                }
            }

            // ensure the provision directory exists
            if (!Directory.Exists(Config.ProvisionDirectory))
            {
                Directory.CreateDirectory(Config.ProvisionDirectory);
            }

            if (Config.bProvision)
            {
                if (File.Exists(Config.ProvisionDirectory + "/" + Config.Provision))
                {
                    return(Config.ProvisionDirectory + "/" + Config.Provision);
                }
            }

            #region remove after we provide an install mechanism
            // copy all of the provisions from the game directory to the library
            if (!String.IsNullOrEmpty(Config.ProjectFile))
            {
                var ProjectFileBuildIOSPath = Path.GetDirectoryName(Config.ProjectFile) + "/Build/IOS/";
                if (Directory.Exists(ProjectFileBuildIOSPath))
                {
                    foreach (string Provision in Directory.EnumerateFiles(ProjectFileBuildIOSPath, "*.mobileprovision", SearchOption.AllDirectories))
                    {
                        if (!File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)) || File.GetLastWriteTime(Config.ProvisionDirectory + Path.GetFileName(Provision)) < File.GetLastWriteTime(Provision))
                        {
                            FileInfo DestFileInfo;
                            if (File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)))
                            {
                                DestFileInfo            = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision));
                                DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly;
                            }
                            File.Copy(Provision, Config.ProvisionDirectory + Path.GetFileName(Provision), true);
                            DestFileInfo            = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision));
                            DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly;
                        }
                    }
                }
            }

            // copy all of the provisions from the engine directory to the library
            {
                if (Directory.Exists(Config.EngineBuildDirectory))
                {
                    foreach (string Provision in Directory.EnumerateFiles(Config.EngineBuildDirectory, "*.mobileprovision", SearchOption.AllDirectories))
                    {
                        if (!File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)) || File.GetLastWriteTime(Config.ProvisionDirectory + Path.GetFileName(Provision)) < File.GetLastWriteTime(Provision))
                        {
                            FileInfo DestFileInfo;
                            if (File.Exists(Config.ProvisionDirectory + Path.GetFileName(Provision)))
                            {
                                DestFileInfo            = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision));
                                DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly;
                            }
                            File.Copy(Provision, Config.ProvisionDirectory + Path.GetFileName(Provision), true);
                            DestFileInfo            = new FileInfo(Config.ProvisionDirectory + Path.GetFileName(Provision));
                            DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly;
                        }
                    }
                }
            }
            #endregion

            // cache the provision library
            Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>();
            foreach (string Provision in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision"))
            {
                MobileProvision p = MobileProvisionParser.ParseFile(Provision);
                ProvisionLibrary.Add(Provision, p);
            }

            Program.Log("Searching for mobile provisions that match the game '{0}' with CFBundleIdentifier='{1}' in '{2}'", GameName, CFBundleIdentifier, Config.ProvisionDirectory);

            // check the cache for a provision matching the app id (com.company.Game)
            // First checking for a contains match and then for a wildcard match
            for (int Phase = 0; Phase < 3; ++Phase)
            {
                foreach (KeyValuePair <string, MobileProvision> Pair in ProvisionLibrary)
                {
                    string          DebugName     = Path.GetFileName(Pair.Key);
                    MobileProvision TestProvision = Pair.Value;

                    Program.LogVerbose("  Phase {0} considering provision '{1}' named '{2}'", Phase, DebugName, TestProvision.ProvisionName);

                    // Validate the name
                    bool bPassesNameCheck = false;
                    if (Phase == 0)
                    {
                        bPassesNameCheck = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier;
                        bNameMatch       = bPassesNameCheck;
                    }
                    else if (Phase == 1)
                    {
                        if (TestProvision.ApplicationIdentifier.Contains("*"))
                        {
                            string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1);
                            if (CompanyName != "*")
                            {
                                CompanyName      = CompanyName.Substring(0, CompanyName.LastIndexOf("."));
                                bPassesNameCheck = CFBundleIdentifier.StartsWith(CompanyName);
                            }
                        }
                    }
                    else
                    {
                        if (TestProvision.ApplicationIdentifier.Contains("*"))
                        {
                            string CompanyName = TestProvision.ApplicationIdentifier.Substring(TestProvision.ApplicationIdentifierPrefix.Length + 1);
                            bPassesNameCheck = CompanyName == "*";
                        }
                    }
                    if (!bPassesNameCheck && bCheckIdentifier)
                    {
                        Program.LogVerbose("  .. Failed phase {0} name check (provision app ID was {1})", Phase, TestProvision.ApplicationIdentifier);
                        continue;
                    }

                    if (Config.bForDistribution)
                    {
                        // check to see if this is a distribution provision
                        bool bDistroProv = (TestProvision.ProvisionedDeviceIDs.Count == 0) && !TestProvision.bDebug;
                        if (!bDistroProv)
                        {
                            Program.LogVerbose("  .. Failed distribution check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count);
                            continue;
                        }
                    }
                    else
                    {
                        // check to see if we pass the debug check for non-distribution
                        bool bPassesDebugCheck = TestProvision.bDebug;
                        if (!bPassesDebugCheck)
                        {
                            Program.LogVerbose("  .. Failed debugging check (mode={0}, get-task-allow={1}, #devices={2})", Config.bForDistribution, TestProvision.bDebug, TestProvision.ProvisionedDeviceIDs.Count);
                            continue;
                        }
                    }

                    // Check to see if the provision is in date
                    DateTime CurrentUTCTime   = DateTime.UtcNow;
                    bool     bPassesDateCheck = (CurrentUTCTime >= TestProvision.CreationDate) && (CurrentUTCTime < TestProvision.ExpirationDate);
                    if (!bPassesDateCheck)
                    {
                        Program.LogVerbose("  .. Failed time period check (valid from {0} to {1}, but UTC time is now {2})", TestProvision.CreationDate, TestProvision.ExpirationDate, CurrentUTCTime);
                        continue;
                    }

                    // check to see if we have a certificate for this provision
                    bool bPassesHasMatchingCertCheck = false;
                    if (bCheckCert)
                    {
                        X509Certificate2 Cert = CodeSignatureBuilder.FindCertificate(TestProvision);
                        bPassesHasMatchingCertCheck = (Cert != null);
                        if (bPassesHasMatchingCertCheck && Config.bCert)
                        {
                            bPassesHasMatchingCertCheck &= (Cert.FriendlyName == Config.Certificate);
                        }
                    }
                    else
                    {
                        bPassesHasMatchingCertCheck = true;
                    }

                    if (!bPassesHasMatchingCertCheck)
                    {
                        Program.LogVerbose("  .. Failed to find a matching certificate that was in date");
                        continue;
                    }

                    // Made it past all the tests
                    Program.LogVerbose("  Picked '{0}' with AppID '{1}' and Name '{2}' as a matching provision for the game '{3}'", DebugName, TestProvision.ApplicationIdentifier, TestProvision.ProvisionName, GameName);
                    return(Pair.Key);
                }
            }

            // check to see if there is already an embedded provision
            string EmbeddedMobileProvisionFilename = Path.Combine(Config.RepackageStagingDirectory, "embedded.mobileprovision");

            Program.Warning("Failed to find a valid matching mobile provision, will attempt to use the embedded mobile provision instead if present");
            return(EmbeddedMobileProvisionFilename);
        }
Exemple #4
0
        /// <summary>
        /// Finds all valid installed provisions
        /// </summary>
        public static void FindProvisions(string CFBundleIdentifier)
        {
            // cache the provision library
            string SelectedProvision = "";
            string SelectedCert      = "";
            string SelectedFile      = "";
            int    FoundName         = -1;
            Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>();

            foreach (string Provision in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision"))
            {
                MobileProvision p = MobileProvisionParser.ParseFile(Provision);

                DateTime EffectiveDate  = p.CreationDate;
                DateTime ExpirationDate = p.ExpirationDate;
                DateTime Now            = DateTime.UtcNow;

                bool             bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                bool             bValid           = false;
                X509Certificate2 Cert             = FindCertificate(p);
                if (Cert != null)
                {
                    bValid = (Cert.NotBefore < Now) && (Cert.NotAfter > Now);
                }
                bool bPassesNameCheck     = p.ApplicationIdentifier.Substring(p.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier;
                bool bPassesCompanyCheck  = false;
                bool bPassesWildCardCheck = false;
                if (p.ApplicationIdentifier.Contains("*"))
                {
                    string CompanyName = p.ApplicationIdentifier.Substring(p.ApplicationIdentifierPrefix.Length + 1);
                    if (CompanyName != "*")
                    {
                        CompanyName         = CompanyName.Substring(0, CompanyName.LastIndexOf("."));
                        bPassesCompanyCheck = CFBundleIdentifier.StartsWith(CompanyName);
                    }
                    else
                    {
                        bPassesWildCardCheck = true;
                    }
                }
                bool   bDistribution = ((p.ProvisionedDeviceIDs.Count == 0) && !p.bDebug);
                string Validity      = "VALID";
                if (!bCertTimeIsValid)
                {
                    Validity = "EXPIRED";
                }
                else if (!bValid)
                {
                    Validity = "NO_CERT";
                }
                else if (!bPassesNameCheck && !bPassesWildCardCheck && !bPassesCompanyCheck)
                {
                    Validity = "NO_MATCH";
                }
                if ((string.IsNullOrWhiteSpace(SelectedProvision) || FoundName < 2) && Validity == "VALID" && !bDistribution)
                {
                    int Prev = FoundName;
                    if (bPassesNameCheck)
                    {
                        FoundName = 2;
                    }
                    else if (bPassesCompanyCheck && FoundName < 1)
                    {
                        FoundName = 1;
                    }
                    else if (bPassesWildCardCheck && FoundName == -1)
                    {
                        FoundName = 0;
                    }
                    if (FoundName != Prev)
                    {
                        SelectedProvision = p.ProvisionName;
                        SelectedFile      = Path.GetFileName(Provision);
                        SelectedCert      = Cert.FriendlyName;
                    }
                }
                Program.LogVerbose("PROVISION-File:{0},Name:{1},Validity:{2},StartDate:{3},EndDate:{4},Type:{5}", Path.GetFileName(Provision), p.ProvisionName, Validity, EffectiveDate.ToString(), ExpirationDate.ToString(), bDistribution ? "DISTRIBUTION" : "DEVELOPMENT");
            }

            Program.LogVerbose("MATCHED-Provision:{0},File:{1},Cert:{2}", SelectedProvision, SelectedFile, SelectedCert);
        }
Exemple #5
0
        /// <summary>
        /// Finds all valid installed certificates
        /// </summary>
        public static void FindCertificates()
        {
            if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
            {
                // run certtool y to get the currently installed certificates
                CertToolData = "";
                Process CertTool = new Process();
                CertTool.StartInfo.FileName               = "/usr/bin/security";
                CertTool.StartInfo.UseShellExecute        = false;
                CertTool.StartInfo.Arguments              = "find-certificate -a -c \"iPhone\" -p";
                CertTool.StartInfo.RedirectStandardOutput = true;
                CertTool.OutputDataReceived              += new DataReceivedEventHandler(OutputReceivedCertToolProcessCall);
                CertTool.Start();
                CertTool.BeginOutputReadLine();
                CertTool.WaitForExit();
                if (CertTool.ExitCode == 0)
                {
                    string header = "-----BEGIN CERTIFICATE-----\n";
                    string footer = "-----END CERTIFICATE-----";
                    int    start  = CertToolData.IndexOf(header);
                    while (start != -1)
                    {
                        start += header.Length;
                        int              end            = CertToolData.IndexOf(footer, start);
                        string           base64         = CertToolData.Substring(start, (end - start));
                        byte[]           certData       = Convert.FromBase64String(base64);
                        X509Certificate2 cert           = new X509Certificate2(certData);
                        DateTime         EffectiveDate  = cert.NotBefore;
                        DateTime         ExpirationDate = cert.NotAfter;
                        DateTime         Now            = DateTime.UtcNow;
                        string           Subject        = cert.Subject;
                        int              SubjStart      = Subject.IndexOf("CN=") + 3;
                        int              SubjEnd        = Subject.IndexOf(",", SubjStart);
                        cert.FriendlyName = Subject.Substring(SubjStart, (SubjEnd - SubjStart));
                        bool bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                        Program.LogVerbose("CERTIFICATE-Name:{0},Validity:{1},StartDate:{2},EndDate:{3}", cert.FriendlyName, bCertTimeIsValid ? "VALID" : "EXPIRED", EffectiveDate.ToString("o"), ExpirationDate.ToString("o"));

                        start = CertToolData.IndexOf(header, start);
                    }
                }
            }
            else
            {
                // Open the personal certificate store on this machine
                X509Store Store = new X509Store();
                Store.Open(OpenFlags.ReadOnly);

                // Try finding all certificates that match either iPhone Developer or iPhone Distribution
                X509Certificate2Collection FoundCerts = Store.Certificates.Find(X509FindType.FindBySubjectName, "iPhone Developer", false);

                foreach (X509Certificate2 TestCert in FoundCerts)
                {
                    DateTime EffectiveDate  = TestCert.NotBefore;
                    DateTime ExpirationDate = TestCert.NotAfter;
                    DateTime Now            = DateTime.Now;

                    bool bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                    Program.LogVerbose("CERTIFICATE-Name:{0},Validity:{1},StartDate:{2},EndDate:{3}", TestCert.FriendlyName, bCertTimeIsValid ? "VALID" : "EXPIRED", EffectiveDate.ToString("o"), ExpirationDate.ToString("o"));
                }

                FoundCerts = Store.Certificates.Find(X509FindType.FindBySubjectName, "iPhone Distribution", false);

                foreach (X509Certificate2 TestCert in FoundCerts)
                {
                    DateTime EffectiveDate  = TestCert.NotBefore;
                    DateTime ExpirationDate = TestCert.NotAfter;
                    DateTime Now            = DateTime.Now;

                    bool bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                    Program.LogVerbose("CERTIFICATE-Name:{0},Validity:{1},StartDate:{2},EndDate:{3}", TestCert.FriendlyName, bCertTimeIsValid ? "VALID" : "EXPIRED", EffectiveDate.ToString("o"), ExpirationDate.ToString("o"));
                }

                Store.Close();
            }
        }
Exemple #6
0
        static int Main(string[] args)
        {
            // remember the working directory at start, as the game path could be relative to this path
            string InitialCurrentDirectory = Environment.CurrentDirectory;

            // set the working directory to the location of the application (so relative paths always work)
            Environment.CurrentDirectory = Path.GetDirectoryName(Application.ExecutablePath);

            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

            // A simple, top-level try-catch block
            try
            {
                if (!ParseCommandLine(ref args))
                {
                    Log("Usage: iPhonePackager <Command> <GameName> [RPCCommand &| Switch]");
                    Log("");
                    Log("Common commands:");
                    Log(" ... RepackageIPA GameName");
                    Log(" ... PackageIPA GameName");
                    Log(" ... PackageApp GameName");
                    Log(" ... Deploy PathToIPA");
                    Log(" ... RepackageFromStage GameName");
                    Log(" ... Devices");
                    Log(" ... Validate");
                    Log(" ... Install");
                    Log("");
                    Log("Configuration switches:");
                    Log("	 -stagedir <path>		  sets the directory to copy staged files from (defaults to none)");
                    Log("	 -project <path>		  path to the project being packaged");
                    Log("	 -provisioning <uuid>	  uuid of the provisioning selected");
                    Log("	 -compress=fast|best|none  packaging compression level (defaults to none)");
                    Log("	 -strip					strip symbols during packaging");
                    Log("	 -config				   game configuration (e.g., Shipping, Development, etc...)");
                    Log("	 -distribution			 packaging for final distribution");
                    Log("	 -codebased				   packaging a c++ code based project");
                    Log("	 -createstub			   packaging stub IPA for later repackaging");
                    Log("	 -mac <MacName>			overrides the machine to use for any Mac operations");
                    Log("	 -arch <Architecture>	  sets the architecture to use (blank for default, -simulator for simulator builds)");
                    Log("	 -device <DeviceID>		sets the device to install the IPA on");
                    Log("");
                    Log("Commands: RPC, Clean");
                    Log("  StageMacFiles, GetIPA, Deploy, Install, Uninstall");
                    Log("");
                    Log("RPC Commands: SetExec, InstallProvision, MakeApp, DeleteIPA, Copy, Kill, Strip, Zip, GenDSYM");
                    Log("");
                    Log("Sample commandlines:");
                    Log(" ... iPhonePackager Deploy UDKGame Release");
                    Log(" ... iPhonePackager RPC SwordGame Shipping MakeApp");
                    return((int)ErrorCodes.Error_Arguments);
                }

                Log("Executing iPhonePackager " + String.Join(" ", args));
                Log("CWD: " + Directory.GetCurrentDirectory());
                Log("Initial Dir: " + InitialCurrentDirectory);
                Log("Env CWD: " + Environment.CurrentDirectory);

                // Ensure shipping configuration for final distributions
                if (Config.bForDistribution && (GameConfiguration != "Shipping"))
                {
                    Program.Warning("Distribution builds should be made in the Shipping configuration!");
                }

                // process the GamePath (if could be ..\Samples\MyDemo\ or ..\Samples\MyDemo\MyDemo.uproject
                GameName = Path.GetFileNameWithoutExtension(GamePath);
                if (GameName.Equals("UE4", StringComparison.InvariantCultureIgnoreCase) || GameName.Equals("Engine", StringComparison.InvariantCultureIgnoreCase))
                {
                    GameName = "UE4Game";
                }

                // setup configuration
                if (!Config.Initialize(InitialCurrentDirectory, GamePath))
                {
                    return((int)ErrorCodes.Error_Arguments);
                }

                switch (MainCommand.ToLowerInvariant())
                {
                case "validate":
                    // check to see if iTunes is installed
                    string dllPath = "";
                    if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix)
                    {
                        ProcessStartInfo StartInfo = new ProcessStartInfo("/usr/bin/xcode-select", "--print-path");
                        StartInfo.UseShellExecute        = false;
                        StartInfo.RedirectStandardOutput = true;
                        StartInfo.CreateNoWindow         = true;

                        using (Process LocalProcess = Process.Start(StartInfo))
                        {
                            StreamReader OutputReader = LocalProcess.StandardOutput;
                            // trim off any extraneous new lines, helpful for those one-line outputs
                            dllPath = OutputReader.ReadToEnd().Trim();
                        }
                    }
                    else
                    {
                        dllPath = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apple Inc.\\Apple Mobile Device Support\\Shared", "iTunesMobileDeviceDLL", null) as string;
                        if (String.IsNullOrEmpty(dllPath) || !File.Exists(dllPath))
                        {
                            dllPath = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apple Inc.\\Apple Mobile Device Support\\Shared", "MobileDeviceDLL", null) as string;
                        }
                    }
                    if (String.IsNullOrEmpty(dllPath) || (!File.Exists(dllPath) && !Directory.Exists(dllPath)))
                    {
                        Error("iTunes Not Found!!", (int)ErrorCodes.Error_SDKNotFound);
                    }
                    else
                    {
                        // validate there is a useable provision and cert
                        MobileProvision  Provision;
                        X509Certificate2 Cert;
                        bool             bHasOverrides;
                        bool             bNameMatch;
                        bool             foundPlist = CodeSignatureBuilder.FindRequiredFiles(out Provision, out Cert, out bHasOverrides, out bNameMatch);
                        if (!foundPlist)
                        {
                            Error("Could not find a valid plist file!!", (int)ErrorCodes.Error_InfoPListNotFound);
                        }
                        else if (!Config.bAutomaticSigning)
                        {
                            if (Provision == null && Cert == null)
                            {
                                Error("No Provision or cert found!!", (int)ErrorCodes.Error_ProvisionAndCertificateNotFound);
                            }
                            else if (Provision == null)
                            {
                                Error("No Provision found!!", (int)ErrorCodes.Error_ProvisionNotFound);
                            }
                            else if (Cert == null)
                            {
                                Error("No Signing Certificate found!!", (int)ErrorCodes.Error_CertificateNotFound);
                            }
                        }
                        else
                        {
                            if (Config.TeamID == null)
                            {
                                Error("No TeamID for automatic signing!!", (int)ErrorCodes.Error_ProvisionNotFound);
                            }
                        }
                    }
                    break;

                case "packageapp":
                    if (CheckArguments())
                    {
                        if (Config.bCreateStubSet)
                        {
                            Error("packageapp cannot be used with the -createstub switch");
                            Program.ReturnCode = (int)ErrorCodes.Error_Arguments;
                        }
                        else
                        {
                            // Create the .app on the Mac
                            CompileTime.CreateApplicationDirOnMac();
                        }
                    }
                    break;

                case "repackagefromstage":
                    if (CheckArguments())
                    {
                        if (Config.bCreateStubSet)
                        {
                            Error("repackagefromstage cannot be used with the -createstub switches");
                            Program.ReturnCode = (int)ErrorCodes.Error_Arguments;
                        }
                        else
                        {
                            bool bProbablyCreatedStub = Utilities.GetEnvironmentVariable("ue.IOSCreateStubIPA", true);
                            if (!bProbablyCreatedStub)
                            {
                                Warning("ue.IOSCreateStubIPA is currently FALSE, which means you may be repackaging with an out of date stub IPA!");
                            }

                            CookTime.RepackageIPAFromStub();
                        }
                    }
                    break;

                // this is the "super fast just move executable" mode for quick programmer iteration
                case "dangerouslyfast":
                    if (CheckArguments())
                    {
                        CompileTime.DangerouslyFastMode();
                    }
                    break;

                case "packageipa":
                    if (CheckArguments())
                    {
                        CompileTime.PackageIPAOnMac();
                    }
                    break;

                case "install":
                    GameName = "";
                    if (Config.bProvision)
                    {
                        ToolsHub.TryInstallingMobileProvision(Config.Provision, false);
                    }
                    if (Config.bCert)
                    {
                        ToolsHub.TryInstallingCertificate_PromptForKey(Config.Certificate, false);
                    }
                    CodeSignatureBuilder.FindCertificates();
                    CodeSignatureBuilder.FindProvisions(Config.OverrideBundleName);
                    break;

                case "certificates":
                {
                    CodeSignatureBuilder.FindCertificates();
                    CodeSignatureBuilder.FindProvisions(Config.OverrideBundleName);
                }
                break;

                case "resigntool":
                    RunInVisualMode(delegate { return(new GraphicalResignTool()); });
                    break;

                case "certrequest":
                    RunInVisualMode(delegate { return(new GenerateSigningRequestDialog()); });
                    break;

                case "gui":
                    RunInVisualMode(delegate { return(ToolsHub.CreateShowingTools()); });
                    break;

                case "devices":
                    ListDevices();
                    break;

                case "signing_match":
                {
                    MobileProvision  Provision;
                    X509Certificate2 Cert;
                    bool             bNameMatch;
                    bool             bHasOverrideFile;
                    if (CodeSignatureBuilder.FindRequiredFiles(out Provision, out Cert, out bHasOverrideFile, out bNameMatch) && Cert != null)
                    {
                        // print out the provision and cert name
                        Program.LogVerbose("CERTIFICATE-{0},PROVISION-{1}", Cert.FriendlyName, Path.GetFileName(Provision.FileName));
                    }
                    else
                    {
                        Program.LogVerbose("No matching Signing Data found!");
                    }
                }
                break;

                default:
                    // Commands by themself default to packaging for the device
                    if (CheckArguments())
                    {
                        ExecuteCommand(MainCommand, MainRPCCommand);
                    }
                    break;
                }
            }
            catch (Exception Ex)
            {
                Error("Application exception: " + Ex.ToString());
                if (ReturnCode == 0)
                {
                    Program.ReturnCode = (int)ErrorCodes.Error_Unknown;
                }
            }
            finally
            {
                if (DeploymentHelper.DeploymentServerProcess != null)
                {
                    DeploymentHelper.DeploymentServerProcess.Close();
                }
            }

            Environment.ExitCode = ReturnCode;
            return(ReturnCode);
        }
Exemple #7
0
        /// <summary>
        /// Finds all valid installed certificates
        /// </summary>
        public static void FindCertificates()
        {
            string[] ValidCertificatePrefixes = { "iPhone Developer", "iPhone Distribution", "Apple Development", "Apple Distribution" };

            X509Certificate2Collection FoundCerts = new X509Certificate2Collection();

            if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
            {
                foreach (string SearchPrefix in ValidCertificatePrefixes)
                {
                    // run certtool y to get the currently installed certificates
                    CertToolData = "";
                    Process CertTool = new Process();
                    CertTool.StartInfo.FileName               = "/usr/bin/security";
                    CertTool.StartInfo.UseShellExecute        = false;
                    CertTool.StartInfo.Arguments              = string.Format("find-certificate -a -c \"{0}\" -p", SearchPrefix);
                    CertTool.StartInfo.RedirectStandardOutput = true;
                    CertTool.OutputDataReceived              += new DataReceivedEventHandler(OutputReceivedCertToolProcessCall);
                    CertTool.Start();
                    CertTool.BeginOutputReadLine();
                    CertTool.WaitForExit();
                    if (CertTool.ExitCode == 0)
                    {
                        string header = "-----BEGIN CERTIFICATE-----\n";
                        string footer = "-----END CERTIFICATE-----";
                        int    start  = CertToolData.IndexOf(header);
                        while (start != -1)
                        {
                            start += header.Length;
                            int              end      = CertToolData.IndexOf(footer, start);
                            string           base64   = CertToolData.Substring(start, (end - start));
                            byte[]           certData = Convert.FromBase64String(base64);
                            X509Certificate2 cert     = new X509Certificate2(certData);
                            FoundCerts.Add(cert);
                            start = CertToolData.IndexOf(header, start);
                        }
                    }
                }
            }
            else
            {
                // Open the personal certificate store on this machine
                X509Store Store = new X509Store();
                Store.Open(OpenFlags.ReadOnly);

                foreach (string SearchPrefix in ValidCertificatePrefixes)
                {
                    FoundCerts.AddRange(Store.Certificates.Find(X509FindType.FindBySubjectName, SearchPrefix, false));
                }

                Store.Close();
            }

            foreach (X509Certificate2 TestCert in FoundCerts)
            {
                DateTime EffectiveDate  = TestCert.NotBefore.ToUniversalTime();
                DateTime ExpirationDate = TestCert.NotAfter.ToUniversalTime();
                DateTime Now            = DateTime.UtcNow;

                bool bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                Program.LogVerbose("CERTIFICATE-Name:{0},Validity:{1},StartDate:{2},EndDate:{3}", CryptoAdapter.GetFriendlyNameFromCert(TestCert), bCertTimeIsValid ? "VALID" : "EXPIRED", EffectiveDate.ToString("o"), ExpirationDate.ToString("o"));
            }
        }
Exemple #8
0
        /// <summary>
        /// Finds all valid installed provisions
        /// </summary>
        public static void FindProvisions(string CFBundleIdentifier)
        {
            if (!Directory.Exists(Config.ProvisionDirectory))
            {
                Program.Error("Could not find provision directory '{0}'.", Config.ProvisionDirectory);
                Program.ReturnCode = (int)ErrorCodes.Error_ProvisionNotFound;
                return;
            }
            // cache the provision library
            string SelectedProvision = "";
            string SelectedCert      = "";
            string SelectedFile      = "";
            int    FoundName         = -1;

            Dictionary <string, MobileProvision> ProvisionLibrary = new Dictionary <string, MobileProvision>();

            foreach (string ProvisionFile in Directory.EnumerateFiles(Config.ProvisionDirectory, "*.mobileprovision"))
            {
                MobileProvision Provision = MobileProvisionParser.ParseFile(ProvisionFile);
                ProvisionLibrary.Add(ProvisionFile, Provision);
            }

            // first sort all profiles so we look at newer ones first.
            IEnumerable <string> ProfileKeys = ProvisionLibrary.Select(KV => KV.Key)
                                               .OrderByDescending(K => ProvisionLibrary[K].CreationDate)
                                               .ToArray();

            // note - all of this is a near duplicate of code in MobileProvisionUtilities, which other functions
            // in this class call to do similar work!
            // @todo - unify all of this.

            foreach (string ProvisionFile in ProfileKeys)
            {
                MobileProvision p = ProvisionLibrary[ProvisionFile];

                DateTime EffectiveDate  = p.CreationDate;
                DateTime ExpirationDate = p.ExpirationDate;
                DateTime Now            = DateTime.UtcNow;

                bool             bCertTimeIsValid = (EffectiveDate < Now) && (ExpirationDate > Now);
                bool             bValid           = false;
                X509Certificate2 Cert             = FindCertificate(p);
                if (Cert != null)
                {
                    bValid = (Cert.NotBefore.ToUniversalTime() < Now) && (Cert.NotAfter.ToUniversalTime() > Now);
                }
                bool bPassesNameCheck     = p.ApplicationIdentifier.Substring(p.ApplicationIdentifierPrefix.Length + 1) == CFBundleIdentifier;
                bool bPassesCompanyCheck  = false;
                bool bPassesWildCardCheck = false;
                if (p.ApplicationIdentifier.Contains("*"))
                {
                    string CompanyName = p.ApplicationIdentifier.Substring(p.ApplicationIdentifierPrefix.Length + 1);
                    if (CompanyName != "*")
                    {
                        CompanyName         = CompanyName.Substring(0, CompanyName.LastIndexOf("."));
                        bPassesCompanyCheck = CFBundleIdentifier.StartsWith(CompanyName);
                    }
                    else
                    {
                        bPassesWildCardCheck = true;
                    }
                }
                bool bIsManaged = false;
                if (p.ProvisionName == "iOS Team Provisioning Profile: " + CFBundleIdentifier)
                {
                    bIsManaged = true;
                }
                bool   bDistribution = ((p.ProvisionedDeviceIDs.Count == 0) && !p.bDebug);
                string Validity      = "VALID";
                if (!bCertTimeIsValid)
                {
                    Validity = "EXPIRED";
                }
                else if (!bValid)
                {
                    Validity = "NO_CERT";
                }
                else if (!bPassesNameCheck && !bPassesWildCardCheck && !bPassesCompanyCheck)
                {
                    Validity = "NO_MATCH";
                }
                if (bIsManaged)
                {
                    Validity = "MANAGED";
                }
                if ((string.IsNullOrWhiteSpace(SelectedProvision) || FoundName < 2) && Validity == "VALID" && !bDistribution)
                {
                    int Prev = FoundName;
                    if (bPassesNameCheck)
                    {
                        FoundName = 2;
                    }
                    else if (bPassesCompanyCheck && FoundName < 1)
                    {
                        FoundName = 1;
                    }
                    else if (bPassesWildCardCheck && FoundName == -1)
                    {
                        FoundName = 0;
                    }
                    if (FoundName != Prev)
                    {
                        SelectedProvision = p.ProvisionName;
                        SelectedFile      = Path.GetFileName(ProvisionFile);
                        SelectedCert      = CryptoAdapter.GetFriendlyNameFromCert(Cert);
                    }
                }
                Program.LogVerbose("PROVISION-File:{0},Name:{1},Validity:{2},StartDate:{3},EndDate:{4},Type:{5}", Path.GetFileName(ProvisionFile), p.ProvisionName, Validity, EffectiveDate.ToString(), ExpirationDate.ToString(), bDistribution ? "DISTRIBUTION" : "DEVELOPMENT");
            }

            Program.LogVerbose("MATCHED-Provision:{0},File:{1},Cert:{2}", SelectedProvision, SelectedFile, SelectedCert);
        }