|
3 | 3 |
|
4 | 4 | #nullable disable
|
5 | 5 |
|
6 |
| -using System.Buffers.Binary; |
7 | 6 | using System.Diagnostics;
|
8 | 7 | using System.Reflection.PortableExecutable;
|
9 | 8 | using System.Text.RegularExpressions;
|
@@ -177,21 +176,12 @@ public void It_codesigns_an_app_targeting_osx(string targetFramework, string rid
|
177 | 176 | var appHostFullPath = Path.Combine(outputDirectory.FullName, testAssetName);
|
178 | 177 |
|
179 | 178 | // Check that the apphost is signed
|
180 |
| - HasMachOSignatureLoadCommand(new FileInfo(appHostFullPath)).Should().BeTrue(); |
181 |
| - // When on a Mac, use the codesign tool to verify the signature as well |
| 179 | + MachOSignature.HasMachOSignatureLoadCommand(new FileInfo(appHostFullPath)).Should().BeTrue(); |
182 | 180 | if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
183 | 181 | {
|
184 |
| - var codesignPath = @"/usr/bin/codesign"; |
185 |
| - new RunExeCommand(Log, codesignPath, ["-s", "-", appHostFullPath]) |
186 |
| - .Execute() |
| 182 | + MachOSignature.HasValidMachOSignature(new FileInfo(appHostFullPath)) |
187 | 183 | .Should()
|
188 |
| - .Fail() |
189 |
| - .And |
190 |
| - .HaveStdErrContaining($"{appHostFullPath}: is already signed"); |
191 |
| - new RunExeCommand(Log, codesignPath, ["-v", appHostFullPath]) |
192 |
| - .Execute() |
193 |
| - .Should() |
194 |
| - .Pass(); |
| 184 | + .BeTrue($"The app host should have a valid Mach-O signature for {rid}."); |
195 | 185 | }
|
196 | 186 | }
|
197 | 187 |
|
@@ -487,62 +477,5 @@ private static bool IsPE32(string path)
|
487 | 477 | return reader.PEHeaders.PEHeader.Magic == PEMagic.PE32;
|
488 | 478 | }
|
489 | 479 | }
|
490 |
| - |
491 |
| - // Reads the Mach-O load commands and returns true if an LC_CODE_SIGNATURE command is found, otherwise returns false |
492 |
| - static bool HasMachOSignatureLoadCommand(FileInfo file) |
493 |
| - { |
494 |
| - /* Mach-O files have the following structure: |
495 |
| - * 32 byte header beginning with a magic number and info about the file and load commands |
496 |
| - * A series of load commands with the following structure: |
497 |
| - * - 4-byte command type |
498 |
| - * - 4-byte command size |
499 |
| - * - variable length command-specific data |
500 |
| - */ |
501 |
| - const uint LC_CODE_SIGNATURE = 0x1D; |
502 |
| - using (var stream = file.OpenRead()) |
503 |
| - { |
504 |
| - // Read the MachO magic number to determine endianness |
505 |
| - Span<byte> eightByteBuffer = stackalloc byte[8]; |
506 |
| - stream.ReadExactly(eightByteBuffer); |
507 |
| - // Determine if the magic number is in the same or opposite endianness as the runtime |
508 |
| - bool reverseEndinanness = BitConverter.ToUInt32(eightByteBuffer.Slice(0, 4)) switch |
509 |
| - { |
510 |
| - 0xFEEDFACF => false, |
511 |
| - 0xCFFAEDFE => true, |
512 |
| - _ => throw new InvalidOperationException("Not a 64-bit Mach-O file") |
513 |
| - }; |
514 |
| - // 4-byte value at offset 16 is the number of load commands |
515 |
| - // 4-byte value at offset 20 is the size of the load commands |
516 |
| - stream.Position = 16; |
517 |
| - ReadUInts(stream, eightByteBuffer, out uint loadCommandsCount, out uint loadCommandsSize); |
518 |
| - // Mach-0 64 byte headers are 32 bytes long, and the first load command will be right after |
519 |
| - stream.Position = 32; |
520 |
| - bool hasSignature = false; |
521 |
| - for (int commandIndex = 0; commandIndex < loadCommandsCount; commandIndex++) |
522 |
| - { |
523 |
| - ReadUInts(stream, eightByteBuffer, out uint commandType, out uint commandSize); |
524 |
| - if (commandType == LC_CODE_SIGNATURE) |
525 |
| - { |
526 |
| - hasSignature = true; |
527 |
| - } |
528 |
| - stream.Position += commandSize - eightByteBuffer.Length; |
529 |
| - } |
530 |
| - Debug.Assert(stream.Position == loadCommandsSize + 32); |
531 |
| - return hasSignature; |
532 |
| - |
533 |
| - void ReadUInts(Stream stream, Span<byte> buffer, out uint val1, out uint val2) |
534 |
| - { |
535 |
| - stream.ReadExactly(buffer); |
536 |
| - val1 = BitConverter.ToUInt32(buffer.Slice(0, 4)); |
537 |
| - val2 = BitConverter.ToUInt32(buffer.Slice(4, 4)); |
538 |
| - if (reverseEndinanness) |
539 |
| - { |
540 |
| - val1 = BinaryPrimitives.ReverseEndianness(val1); |
541 |
| - val2 = BinaryPrimitives.ReverseEndianness(val2); |
542 |
| - } |
543 |
| - } |
544 |
| - } |
545 |
| - } |
546 |
| - |
547 | 480 | }
|
548 | 481 | }
|
0 commit comments