Skip to content

Commit

Permalink
Fix up strong name signing for Unified Build (dotnet#15166)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmitche authored Oct 11, 2024
1 parent 712dea2 commit 7065358
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 49 deletions.
5 changes: 4 additions & 1 deletion src/Microsoft.DotNet.Arcade.Sdk/tools/Sign.proj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@

<_DotNetCoreRequired>false</_DotNetCoreRequired>
<_DotNetCoreRequired Condition="'$(_DryRun)' != 'true' and '$(OS)' != 'Windows_NT'">true</_DotNetCoreRequired>

<!-- SN is only available on Windows -->
<SNBinaryPath Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(NuGetPackageRoot)sn\$(SNVersion)\sn.exe</SNBinaryPath>
</PropertyGroup>

<Error Condition="'$(AllowEmptySignList)' != 'true' AND '@(ItemsToSign)' == ''"
Expand Down Expand Up @@ -91,7 +94,7 @@
LogDir="$(ArtifactsLogDir)"
MSBuildPath="$(_DesktopMSBuildPath)"
DotNetPath="$(_DotNetCorePath)"
SNBinaryPath="$(NuGetPackageRoot)sn\$(SNVersion)\sn.exe"
SNBinaryPath="$(SNBinaryPath)"
MicroBuildCorePath="$(NuGetPackageRoot)microbuild.core\$(MicroBuildCoreVersion)"
WixToolsPath="$(WixInstallPath)"
TarToolPath="$(NuGetPackageRoot)microsoft.dotnet.tar\$(MicrosoftDotNetSignToolVersion)\tools\net9.0\any\Microsoft.Dotnet.Tar.dll"
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.DotNet.Arcade.Sdk/tools/Sign.props
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
<StrongNameSignInfo Include="SilverlightCert121" PublicKeyToken="7cec85d7bea7798e" CertificateName="Microsoft400" />
<StrongNameSignInfo Include="StrongName" PublicKeyToken="b77a5c561934e089" CertificateName="Microsoft400" />
<StrongNameSignInfo Include="StrongName" PublicKeyToken="b03f5f7f11d50a3a" CertificateName="Microsoft400" />
<StrongNameSignInfo Include="$(MSBuildThisFileDirectory)snk\Open.snk" PublicKeyToken="cc7b13ffcd2ddd51" CertificateName="Microsoft400" />
<!-- Do not include specific key files if full assembly signing is not supported, as they will not be usable when we sign. -->
<StrongNameSignInfo Include="$(MSBuildThisFileDirectory)snk\Open.snk" PublicKeyToken="cc7b13ffcd2ddd51" CertificateName="Microsoft400" Condition="'$(FullAssemblySigningSupported)' != 'false'" />

<!--
Map of file extensions to default certificate name. Files with these extensions are
Expand Down
3 changes: 3 additions & 0 deletions src/Microsoft.DotNet.SignTool.Tests/FakeSignTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.IO.Packaging;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Collections.Generic;

namespace Microsoft.DotNet.SignTool
{
Expand All @@ -23,6 +24,8 @@ public override void RemovePublicSign(string assemblyPath)
{
}

public override bool LocalStrongNameSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> files) => true;

public override bool VerifySignedPEFile(Stream stream)
{
var buffer = new byte[_stamp.Length];
Expand Down
14 changes: 14 additions & 0 deletions src/Microsoft.DotNet.SignTool/src/RealSignTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace Microsoft.DotNet.SignTool
{
Expand Down Expand Up @@ -142,5 +143,18 @@ public override bool VerifySignedVSIXFileMarker(string filePath)
{
return VerifySignatures.VerifySignedVSIXByFileMarker(filePath);
}

public override bool LocalStrongNameSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> files)
{
foreach (var file in files)
{
if (file.SignInfo.ShouldLocallyStrongNameSign)
{
return LocalStrongNameSign(file);
}
}

return true;
}
}
}
68 changes: 32 additions & 36 deletions src/Microsoft.DotNet.SignTool/src/SignTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal SignTool(SignToolArgs args, TaskLoggingHelper log)

public abstract void RemovePublicSign(string assemblyPath);

public abstract bool LocalStrongNameSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> files);

public abstract bool VerifySignedPEFile(Stream stream);
public abstract bool VerifySignedPowerShellFile(string filePath);
public abstract bool VerifySignedNugetFileMarker(string filePath);
Expand All @@ -45,42 +47,6 @@ public bool Sign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo>
&& AuthenticodeSign(buildEngine, round, files);
}

private bool LocalStrongNameSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> files)
{
foreach (var file in files)
{
if (file.SignInfo.ShouldLocallyStrongNameSign)
{
if (!File.Exists(_args.SNBinaryPath) || !_args.SNBinaryPath.EndsWith("sn.exe"))
{
_log.LogError($"Found file that need to be strong-name sign ({file.FullPath}) but path to 'sn.exe' wasn't specified.");
return false;
}

_log.LogMessage($"Strong-name signing {file.FullPath} locally.");

// sn -R <path_to_file> <path_to_snk>
var process = Process.Start(new ProcessStartInfo()
{
FileName = _args.SNBinaryPath,
Arguments = $@"-R ""{file.FullPath}"" ""{file.SignInfo.StrongName}""",
UseShellExecute = false,
WorkingDirectory = TempDir,
});

process.WaitForExit();

if (process.ExitCode != 0)
{
_log.LogError($"Failed to strong-name sign file {file.FullPath}");
return false;
}
}
}

return true;
}

private bool AuthenticodeSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> filesToSign)
{
var signingDir = Path.Combine(_args.TempDir, "Signing");
Expand Down Expand Up @@ -217,5 +183,35 @@ private static void AppendLine(StringBuilder builder, int depth, string text)

builder.AppendLine(text);
}

protected bool LocalStrongNameSign(FileSignInfo file)
{
if (!File.Exists(_args.SNBinaryPath) || !_args.SNBinaryPath.EndsWith("sn.exe"))
{
_log.LogError($"Found file that needs to be strong-name sign ({file.FullPath}), but path to 'sn.exe' wasn't specified.");
return false;
}

_log.LogMessage($"Strong-name signing {file.FullPath} locally.");

// sn -R <path_to_file> <path_to_snk>
var process = Process.Start(new ProcessStartInfo()
{
FileName = _args.SNBinaryPath,
Arguments = $@"-R ""{file.FullPath}"" ""{file.SignInfo.StrongName}""",
UseShellExecute = false,
WorkingDirectory = TempDir,
});

process.WaitForExit();

if (process.ExitCode != 0)
{
_log.LogError($"Failed to strong-name sign file {file.FullPath}");
return false;
}

return true;
}
}
}
11 changes: 0 additions & 11 deletions src/Microsoft.DotNet.SignTool/src/SignToolTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,6 @@ public void ExecuteImpl()
Log.LogError($"An incorrect full path to 'sn.exe' was specified: {SNBinaryPath}");
return;
}

var strongNameLocally = StrongNameSignInfo != null
&& StrongNameSignInfo
.Where(ti => !string.IsNullOrEmpty(ti.ItemSpec) && ti.ItemSpec.EndsWith(".snk", StringComparison.OrdinalIgnoreCase))
.Any();

if (!isValidSNPath && strongNameLocally)
{
Log.LogError($"An incorrect full path to 'sn.exe' was specified: {SNBinaryPath}");
return;
}
}
if(WixToolsPath != null && !Directory.Exists(WixToolsPath))
{
Expand Down
24 changes: 24 additions & 0 deletions src/Microsoft.DotNet.SignTool/src/ValidationOnlySignTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Microsoft.DotNet.SignTool
{
Expand All @@ -21,6 +23,28 @@ internal ValidationOnlySignTool(SignToolArgs args, TaskLoggingHelper log)
TestSign = args.TestSign;
}

public override bool LocalStrongNameSign(IBuildEngine buildEngine, int round, IEnumerable<FileSignInfo> files)
{
// On non-Windows, we skip strong name signing because sn.exe is not available.
// We could skip it always in the validation sign tool, but it is useful to
// get some level of validation.

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return true;
}

foreach (var file in files)
{
if (file.SignInfo.ShouldLocallyStrongNameSign)
{
return LocalStrongNameSign(file);
}
}

return true;
}

public override void RemovePublicSign(string assemblyPath)
{
}
Expand Down

0 comments on commit 7065358

Please sign in to comment.