mirror of
https://github.com/whoeevee/ivinject.git
synced 2026-01-09 00:25:03 +01:00
provisioning profiles support
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user