provisioning profiles support

This commit is contained in:
eevee
2025-09-14 01:24:47 +03:00
parent 5f4adec22c
commit 68722c2084
12 changed files with 128 additions and 33 deletions
@@ -48,7 +48,7 @@ internal static class CodesigningMachOExtensions
new ProcessStartInfo
{
FileName = "codesign",
Arguments = $"--remove-signature \"{binary.FullName}\""
ArgumentList = { "--remove-signature", binary.FullName }
}
);
@@ -62,7 +62,7 @@ internal static class CodesigningMachOExtensions
new ProcessStartInfo
{
FileName = "codesign",
Arguments = $"-d --entitlements {outputFilePath} --xml \"{binary.FullName}\"",
ArgumentList = { "-d", "--entitlements", outputFilePath, "--xml", binary.FullName },
RedirectStandardError = true
}
);
@@ -195,6 +195,9 @@ internal class CodesigningManager(ILogger logger) : IDisposable
if (!await SignBinary(MainBinary, signingInfo))
return false;
if (signingInfo.IsFromProvisioningProfile)
signingInfo.Entitlements!.Delete();
logger.LogInformation(
"Signed {} binaries ({} main executables) with the specified identity",
_allBinaries.Count,
+18 -2
View File
@@ -50,6 +50,16 @@ internal class IviRootCommand : RootCommand
AllowMultipleArgumentsPerToken = true
};
private readonly Option<FileInfo> _provisioningProfileOption = new(
"--profile",
"Provisioning profile to extract entitlements, signing identity, and bundle ID"
);
private readonly Option<bool> _profileBundleIdOption = new(
"--profile-bundle-id",
"Replace the bundle ID with the one in the provisioning profile"
);
private readonly Option<string> _codesignIdentityOption = new(
"--sign",
"The identity for code signing (use \"-\" for ad hoc, a.k.a. fake signing)"
@@ -63,7 +73,7 @@ internal class IviRootCommand : RootCommand
//
private readonly Option<string> _customBundleIdOption = new(
"--bundleId",
"--bundle-id",
"The custom identifier that will be applied to application bundles"
);
@@ -86,9 +96,11 @@ internal class IviRootCommand : RootCommand
internal IviRootCommand() : base("The most demure iOS app injector and signer")
{
_itemsOption.AddAlias("-i");
_provisioningProfileOption.AddAlias("-p");
_codesignIdentityOption.AddAlias("-s");
_compressionLevelOption.AddAlias("--level");
_codesignEntitlementsOption.AddAlias("-e");
_compressionLevelOption.AddAlias("--level");
_customBundleIdOption.AddAlias("-b");
_enableDocumentsSupportOption.AddAlias("-d");
@@ -101,6 +113,8 @@ internal class IviRootCommand : RootCommand
AddOption(_compressionLevelOption);
AddOption(_itemsOption);
AddOption(_provisioningProfileOption);
AddOption(_profileBundleIdOption);
AddOption(_codesignIdentityOption);
AddOption(_codesignEntitlementsOption);
@@ -120,6 +134,8 @@ internal class IviRootCommand : RootCommand
_overwriteOutputOption,
_compressionLevelOption,
_itemsOption,
_provisioningProfileOption,
_profileBundleIdOption,
_codesignIdentityOption,
_codesignEntitlementsOption,
_customBundleIdOption,
@@ -12,6 +12,8 @@ internal class IviRootCommandParametersBinder(
Option<bool> overwriteOutputOption,
Option<CompressionLevel> compressionLevelOption,
Option<IEnumerable<FileInfo>> itemsOption,
Option<FileInfo> provisioningProfileOption,
Option<bool> profileBundleIdOption,
Option<string> codesignIdentityOption,
Option<FileInfo> codesignEntitlementsOption,
Option<string> customBundleIdOption,
@@ -33,12 +35,16 @@ internal class IviRootCommandParametersBinder(
var items =
bindingContext.ParseResult.GetValueForOption(itemsOption);
var provisioningProfile =
bindingContext.ParseResult.GetValueForOption(provisioningProfileOption);
var profileBundleId =
bindingContext.ParseResult.GetValueForOption(profileBundleIdOption);
var codesignIdentity =
bindingContext.ParseResult.GetValueForOption(codesignIdentityOption);
var codesignEntitlements =
bindingContext.ParseResult.GetValueForOption(codesignEntitlementsOption);
var bundleId =
var customBundleId =
bindingContext.ParseResult.GetValueForOption(customBundleIdOption);
var enableDocumentsSupport =
bindingContext.ParseResult.GetValueForOption(enableDocumentsSupportOption);
@@ -46,15 +52,43 @@ internal class IviRootCommandParametersBinder(
bindingContext.ParseResult.GetValueForOption(removeSupportedDevicesOption);
var directoriesToRemove =
bindingContext.ParseResult.GetValueForOption(directoriesToRemoveOption);
IviPackagingInfo? packagingInfo;
if (bundleId is null
&& directoriesToRemove is null
&& !enableDocumentsSupport
&& !removeSupportedDevices)
packagingInfo = null;
else
IviSigningInfo? signingInfo = null;
IviPackagingInfo? packagingInfo = null;
var profileInfo = provisioningProfile is not null
? ProvisioningProfileParser.Parse(provisioningProfile)
: null;
if (profileInfo is not null)
{
signingInfo = new IviSigningInfo
{
Identity = profileInfo.Identity,
Entitlements = profileInfo.Entitlements,
IsFromProvisioningProfile = true
};
}
else if (codesignIdentity is not null)
{
signingInfo = new IviSigningInfo
{
Identity = codesignIdentity,
Entitlements = codesignEntitlements
};
}
var bundleId = customBundleId;
if (profileInfo is not null && profileBundleId)
bundleId = profileInfo.BundleId;
if (bundleId is not null
|| directoriesToRemove is not null
|| enableDocumentsSupport
|| removeSupportedDevices
)
{
packagingInfo = new IviPackagingInfo
{
CustomBundleId = bundleId,
@@ -62,6 +96,7 @@ internal class IviRootCommandParametersBinder(
RemoveSupportedDevices = removeSupportedDevices,
DirectoriesToRemove = directoriesToRemove ?? []
};
}
return new IviParameters
{
@@ -70,13 +105,7 @@ internal class IviRootCommandParametersBinder(
OverwriteOutput = overwriteOutput,
CompressionLevel = compressionLevel,
InjectionEntries = items?.Select(item => new IviInjectionEntry(item)) ?? [],
SigningInfo = codesignIdentity is null
? null
: new IviSigningInfo
{
Identity = codesignIdentity,
Entitlements = codesignEntitlements
},
SigningInfo = signingInfo,
PackagingInfo = packagingInfo
};
}
@@ -2,6 +2,7 @@ namespace ivinject.Features.Command.Models;
internal class IviSigningInfo
{
internal bool IsFromProvisioningProfile { get; init; }
internal required string Identity { get; init; }
internal bool IsAdHocSigning => Identity == "-";
internal FileInfo? Entitlements { get; init; }
+8
View File
@@ -0,0 +1,8 @@
namespace ivinject.Features.Command.Models;
internal class ProfileInfo
{
internal required FileInfo Entitlements { get; init; }
internal required string Identity { get; set; }
internal required string BundleId { get; set; }
}
@@ -0,0 +1,39 @@
using System.Diagnostics;
using Claunia.PropertyList;
using ivinject.Features.Command.Models;
namespace ivinject.Features.Command;
internal static class ProvisioningProfileParser
{
internal static ProfileInfo Parse(FileInfo profile)
{
using var process = Process.Start(
new ProcessStartInfo
{
FileName = "security",
ArgumentList = { "cms", "-D", "-i", profile.FullName },
RedirectStandardOutput = true
}
);
process!.WaitForExit();
var dictionary = (NSDictionary)PropertyListParser.Parse(process.StandardOutput.BaseStream);
var entitlements = (NSDictionary)dictionary["Entitlements"];
var teamIdentifier = ((NSString)entitlements["com.apple.developer.team-identifier"]).Content;
var bundleId = ((NSString)entitlements["application-identifier"]).Content[11..];
var entitlementsFile = Path.GetTempFileName();
File.WriteAllText(entitlementsFile, entitlements.ToXmlPropertyList());
var entitlementsFileInfo = new FileInfo(entitlementsFile);
return new ProfileInfo
{
BundleId = bundleId,
Identity = teamIdentifier,
Entitlements = entitlementsFileInfo
};
}
}
+2 -2
View File
@@ -19,7 +19,7 @@ internal class DebManager(IviInjectionEntry debEntry) : IDisposable
new ProcessStartInfo
{
FileName = "tar",
Arguments = $"-xf {debEntry.FullName} --directory={_tempPath}"
ArgumentList = { "-xf", debEntry.FullName, $"--directory={_tempPath}" }
}
);
@@ -31,7 +31,7 @@ internal class DebManager(IviInjectionEntry debEntry) : IDisposable
new ProcessStartInfo
{
FileName = "tar",
Arguments = $"-xf {dataArchive}",
ArgumentList = { "-xf", dataArchive },
WorkingDirectory = _tempPath
}
);
+4 -4
View File
@@ -13,7 +13,7 @@ internal static class DependencyExtensions
new ProcessStartInfo
{
FileName = "otool",
Arguments = $"-L \"{binary.FullName}\"",
ArgumentList = { "-L", binary.FullName },
RedirectStandardOutput = true
}
);
@@ -35,7 +35,7 @@ internal static class DependencyExtensions
new ProcessStartInfo
{
FileName = "install_name_tool",
Arguments = $"-change {oldPath} {newPath} \"{binary.FullName}\"",
ArgumentList = { "-change", oldPath, newPath, binary.FullName },
RedirectStandardError = true
}
);
@@ -52,7 +52,7 @@ internal static class DependencyExtensions
new ProcessStartInfo
{
FileName = "install_name_tool",
Arguments = $"-add_rpath {rPath} \"{binary.FullName}\"",
ArgumentList = { "-add_rpath", rPath, binary.FullName },
RedirectStandardOutput = true
}
);
@@ -70,7 +70,7 @@ internal static class DependencyExtensions
new ProcessStartInfo
{
FileName = "insert-dylib",
Arguments = $"{dependency} \"{binary.FullName}\" --all-yes --inplace",
ArgumentList = { dependency, binary.FullName, "--all-yes", "--inplace" },
RedirectStandardOutput = true
}
);