Skip to content

Commit

Permalink
Bundle: Update ResourceRules to match those observed in an iOS package
Browse files Browse the repository at this point in the history
  • Loading branch information
qmfrederik committed Nov 28, 2022
1 parent ea60e7b commit 4718606
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 16 deletions.
77 changes: 77 additions & 0 deletions Melanzana.CodeSign.Tests/SignerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.IO;
using System.IO.Compression;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace Melanzana.CodeSign.Tests
{
public class SignerTests
{
private const string WebDriverAgentFileName = "WebDriverAgentRunner-Runner.zip";

[Theory]
[InlineData("Frameworks/XCTAutomationSupport.framework")]
[InlineData("Frameworks/XCTestCore.framework")]
[InlineData("Frameworks/XCUIAutomation.framework")]
[InlineData("Frameworks/XCUnit.framework")]
public async Task CodeResources_Roundtrip(string nestedBundlePath)
{
// Extract a fresh copy of the WebDriverAgent into a directory dedicated to this test.
var testDirectory = Path.GetFullPath(nameof(CodeResources_Roundtrip));
await ExtractWebDriverAgent(testDirectory);

// Build the resource seal and convert to a XML property list
var bundleDirectory = Path.Combine(testDirectory, "WebDriverAgentRunner-Runner.app", nestedBundlePath);
var bundle = new Bundle(bundleDirectory);
var signer = new Signer(new CodeSignOptions());
var actual = signer.BuildResourceSeal(bundle).ToXmlPropertyList();

// The newly created resource seal should match the original resource seal
var expected = File.ReadAllText(Path.Combine(bundleDirectory, "_CodeSignature/CodeResources"));
Assert.Equal(expected, actual);
}

private async Task ExtractWebDriverAgent(string path)
{
await DownloadWebDriverAgent(WebDriverAgentFileName);

if (!Directory.Exists(path))
{
using (Stream stream = File.OpenRead(WebDriverAgentFileName))
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read))
{
archive.ExtractToDirectory(path);
}
}
}

private async Task DownloadWebDriverAgent(string path, string version = "v4.10.10")
{
if (!File.Exists(path))
{
using (var targetStream = File.Create(path))
using (var client = new HttpClient())
using (var sourceStream = await client.GetStreamAsync($"https://github.com/appium/WebDriverAgent/releases/download/{version}/WebDriverAgentRunner-Runner.zip"))
{
await sourceStream.CopyToAsync(targetStream);
}
}
}

private static void DeleteResources(string path)
{
foreach (var dir in Directory.GetDirectories(path))
{
if (Path.GetFileName(dir) == "_CodeSignature")
{
Directory.Delete(dir, recursive: true);
}
else
{
DeleteResources(dir);
}
}
}
}
}
28 changes: 17 additions & 11 deletions Melanzana.CodeSign/Bundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public Bundle(string path)
{
mainExecutable = (string)bundleExecutable;
}

if (!File.Exists(Path.Combine(ContentsPath, mainExecutable)))
{
mainExecutable = null;
Expand Down Expand Up @@ -89,8 +89,18 @@ public void AddResourceRules(ResourceBuilder builder, bool useV2Rules = true)

if (useV2Rules)
{
builder.AddRule(new ResourceRule(".*\\.dSYM($|/)") { Weight = 11 });

builder.AddRule(new ResourceRule("^(.*/)?\\.DS_Store$") { IsOmitted = true, Weight = 2000 });

builder.AddRule(new ResourceRule("^.*"));

builder.AddRule(new ResourceRule("^.*\\.lproj/") { IsOptional = true, Weight = 1000 });

builder.AddRule(new ResourceRule("^.*\\.lproj/locversion.plist$") { IsOmitted = true, Weight = 1100 });

builder.AddRule(new ResourceRule("^Base\\.lproj/") { Weight = 1010 });

// On macOS include nested signatures
if (hasResources)
{
Expand All @@ -99,27 +109,23 @@ public void AddResourceRules(ResourceBuilder builder, bool useV2Rules = true)
builder.AddRule(new ResourceRule($"^{resourcePrefix}") { Weight = 20 });
}

builder.AddRule(new ResourceRule(".*\\.dSYM($|/)") { Weight = 11 });

// Exclude specific files:
builder.AddRule(new ResourceRule("^Info\\.plist$") { IsOmitted = true, Weight = 20 });
builder.AddRule(new ResourceRule("^PkgInfo$") { IsOmitted = true, Weight = 20 });

// Include specific files:
builder.AddRule(new ResourceRule("^embedded\\.provisionprofile$") { Weight = 20 });
builder.AddRule(new ResourceRule("^version.plist$") { Weight = 20 });

builder.AddRule(new ResourceRule("^(.*/)?\\.DS_Store$") { IsOmitted = true, Weight = 2000 });
builder.AddRule(new ResourceRule("^version\\.plist$") { Weight = 20 });
}
else
{
builder.AddRule(new ResourceRule("^version.plist$"));
builder.AddRule(new ResourceRule(hasResources ? $"^{resourcePrefix}" : "^.*"));
}

builder.AddRule(new ResourceRule($"^{resourcePrefix}.*\\.lproj/") { IsOptional = true, Weight = 1000 });
builder.AddRule(new ResourceRule($"^{resourcePrefix}Base\\.lproj/") { Weight = 1010 });
builder.AddRule(new ResourceRule($"^{resourcePrefix}.*\\.lproj/locversion.plist$") { IsOmitted = true, Weight = 1100 });
builder.AddRule(new ResourceRule($"^{resourcePrefix}.*\\.lproj/") { IsOptional = true, Weight = 1000 });
builder.AddRule(new ResourceRule($"^{resourcePrefix}.*\\.lproj/locversion.plist$") { IsOmitted = true, Weight = 1100 });
builder.AddRule(new ResourceRule($"^{resourcePrefix}Base\\.lproj/") { Weight = 1010 });
builder.AddRule(new ResourceRule("^version.plist$"));
}

// Add implicit exclusions
builder.AddExclusion("_CodeSignature");
Expand Down
10 changes: 5 additions & 5 deletions Melanzana.CodeSign/Signer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,22 +262,22 @@ private static NSDictionary BuildResourceRulesPList(IEnumerable<ResourceRule> ru
else
{
var rulePList = new NSDictionary();
if (rule.Weight != 1)
rulePList.Add("weight", (double)rule.Weight);
if (rule.IsOmitted)
rulePList.Add("omit", true);
if (rule.IsOptional)
rulePList.Add("optional", true);
if (rule.IsNested)
rulePList.Add("nested", true);
if (rule.IsOmitted)
rulePList.Add("omit", true);
if (rule.Weight != 1)
rulePList.Add("weight", (double)rule.Weight);
rulesPList.Add(rule.Pattern, rulePList);
}
}

return rulesPList;
}

private NSDictionary BuildResourceSeal(Bundle bundle)
public NSDictionary BuildResourceSeal(Bundle bundle)
{
var sha1 = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
var sha256 = IncrementalHash.CreateHash(HashAlgorithmName.SHA256);
Expand Down

0 comments on commit 4718606

Please sign in to comment.