diff options
-rw-r--r-- | config/SignTask.cs | 133 | ||||
-rw-r--r-- | config/ice.common.sign.targets | 23 | ||||
-rw-r--r-- | cpp/msbuild/ice.sign.targets | 58 | ||||
-rw-r--r-- | csharp/msbuild/ice.sign.targets | 50 |
4 files changed, 215 insertions, 49 deletions
diff --git a/config/SignTask.cs b/config/SignTask.cs new file mode 100644 index 00000000000..a4892e4cb4c --- /dev/null +++ b/config/SignTask.cs @@ -0,0 +1,133 @@ +// +// Copyright (c) ZeroC, Inc. All rights reserved. +// + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +public class SignTask : Task +{ + [Required] + public string WorkingDirectory + { + get; + set; + } + + [Required] + public ITaskItem[] Files + { + get; + set; + } + + public string AdditionalOptions + { + get; + set; + } + + protected string GenerateCommandLineCommands() + { + CommandLineBuilder builder = new CommandLineBuilder(false); + builder.AppendSwitch("sign"); + if(AdditionalOptions != null) + { + builder.AppendTextUnquoted(" "); + builder.AppendTextUnquoted(AdditionalOptions); + } + builder.AppendFileNamesIfNotNull(Files, " "); + return builder.ToString(); + } + + public override bool Execute() + { + string commandLineCommands = GenerateCommandLineCommands(); + int status = 0; + string output = ""; + string error = ""; + int nRetries = 0; + while(nRetries++ < 10) + { + output = ""; + error = ""; + status = RunCommand(WorkingDirectory, "signtool.exe", commandLineCommands, ref output, ref error); + if(status != 0 && error.IndexOf("timestamp server") != -1) + { + Thread.Sleep(10); + continue; + } + break; + } + + if(status == 0) + { + Log.LogMessage(MessageImportance.High, output.Trim()); + } + else + { + Log.LogError(error.Trim()); + } + + return status == 0; + } + + public class StreamReader + { + public string Output { get; private set; } + + public string Error { get; private set; } + + public void ouput(object sendingProcess, DataReceivedEventArgs outLine) + { + if(outLine.Data != null) + { + Output += outLine.Data + "\n"; + } + } + + public void error(object sendingProcess, DataReceivedEventArgs outLine) + { + if(outLine.Data != null) + { + Error += outLine.Data + "\n"; + } + } + } + + public static int RunCommand(string workingDir, string command, string args, ref string output, ref string error) + { + Process process = new Process(); + process.StartInfo.FileName = command; + process.StartInfo.Arguments = args; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.WorkingDirectory = workingDir; + + var streamReader = new StreamReader(); + process.OutputDataReceived += new DataReceivedEventHandler(streamReader.ouput); + process.ErrorDataReceived += new DataReceivedEventHandler(streamReader.error); + + try + { + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + error = streamReader.Error; + output = streamReader.Output; + return process.ExitCode; + } + catch(Exception ex) + { + error = ex.ToString(); + return 1; + } + } +} diff --git a/config/ice.common.sign.targets b/config/ice.common.sign.targets new file mode 100644 index 00000000000..87dd0b189a5 --- /dev/null +++ b/config/ice.common.sign.targets @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <TimeStampServer>http://timestamp.digicert.com</TimeStampServer> + <SignCommandSHA1>/f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /tr $(TimeStampServer)</SignCommandSHA1> + <SignCommandSHA256>/f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /tr $(TimeStampServer) /td sha256 /fd sha256 /as</SignCommandSHA256> + </PropertyGroup> + + <!-- Authenticode sign task that retries on failures --> + <UsingTask TaskName="SignTask" + TaskFactory="CodeTaskFactory" + AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> + <ParameterGroup> + <WorkingDirectory ParameterType="System.String" Required="true"/> + <AdditionalOptions ParameterType="System.String" Required="true"/> + <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="True"/> + </ParameterGroup> + <Task> + <Code Type="Class" Language="cs" Source="$(MSBuildThisFileDirectory)/SignTask.cs" /> + </Task> + </UsingTask> + +</Project> diff --git a/cpp/msbuild/ice.sign.targets b/cpp/msbuild/ice.sign.targets index 609e4edf735..3e871ca69d7 100644 --- a/cpp/msbuild/ice.sign.targets +++ b/cpp/msbuild/ice.sign.targets @@ -1,34 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup> - <TimeStampServer>http://timestamp.digicert.com</TimeStampServer> - <SignCommandSHA1>signtool sign /f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /t $(TimeStampServer)</SignCommandSHA1> - <SignCommandSHA256>signtool sign /f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /tr $(TimeStampServer) /td sha256 /fd sha256 /as</SignCommandSHA256> - <SignTarget>$(OutDir)$(TargetName)$(TargetExt)</SignTarget> - </PropertyGroup> + <Import Project="$(MSBuildThisFileDirectory)/../../config/ice.common.sign.targets" /> + <PropertyGroup> + <SignTarget>$(OutDir)$(TargetName)$(TargetExt)</SignTarget> + </PropertyGroup> - <Target Name="SignPackage" - Condition="Exists('$(SIGN_CERTIFICATE)') and (!Exists('$(IntDir)sign.log') or $([System.IO.File]::GetLastWriteTime('$(SignTarget)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(IntDir)sign.log').Ticks))"> - <Message Text="Signing $(SignTarget)" /> + <Target Name="SignPackage" + Condition="Exists('$(SIGN_CERTIFICATE)') and (!Exists('$(IntDir)sign.log') or $([System.IO.File]::GetLastWriteTime('$(SignTarget)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(IntDir)sign.log').Ticks))"> + <Message Text="Signing $(SignTarget)" /> - <Exec Command="$(SignCommandSHA1) $(SignTarget)" EchoOff="yes"/> - <Exec Command="$(SignCommandSHA256) $(SignTarget)" EchoOff="yes" - Condition="'$(DefaultPlatformToolset)' != 'v100'"/> + <!-- Authenticode signing --> + <SignTask + WorkingDirectory="$(OutDir)" + AdditionalOptions="$(SignCommandSHA1)" + Files="$(TargetName)$(TargetExt)"/> - <WriteLinesToFile File = "$(IntDir)sign.log" - Encoding = "Unicode" - Overwrite = "true" - Lines = "Signing $(SignTarget)"/> - </Target> + <SignTask + WorkingDirectory="$(OutDir)" + AdditionalOptions="$(SignCommandSHA256)" + Files="$(TargetName)$(TargetExt)" + Condition="'$(DefaultPlatformToolset)' != 'v100'"/> - <Target Name="SignPackageClean" AfterTargets="Clean"> - <Delete Files="$(IntDir)sign.log" /> - </Target> + <WriteLinesToFile File = "$(IntDir)sign.log" + Encoding = "Unicode" + Overwrite = "true" + Lines = "Signing $(SignTarget)"/> + </Target> - <PropertyGroup> - <BuildDependsOn> - $(BuildDependsOn); - SignPackage - </BuildDependsOn> - </PropertyGroup> + <Target Name="SignPackageClean" AfterTargets="Clean"> + <Delete Files="$(IntDir)sign.log" /> + </Target> + + <PropertyGroup> + <BuildDependsOn> + $(BuildDependsOn); + SignPackage + </BuildDependsOn> + </PropertyGroup> </Project> diff --git a/csharp/msbuild/ice.sign.targets b/csharp/msbuild/ice.sign.targets index 0b65ae746af..6b053d05b02 100644 --- a/csharp/msbuild/ice.sign.targets +++ b/csharp/msbuild/ice.sign.targets @@ -1,40 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup> - <TimeStampServer>http://timestamp.digicert.com</TimeStampServer> - <SignCommandSHA1>signtool sign /f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /t $(TimeStampServer)</SignCommandSHA1> - <SignCommandSHA256>signtool sign /f "$(SIGN_CERTIFICATE)" /p $(SIGN_PASSWORD) /tr $(TimeStampServer) /td sha256 /fd sha256 /as</SignCommandSHA256> - </PropertyGroup> - - <PropertyGroup Condition="'$(PUBLIC_KEYFILE)' != '' Or '$(KEYFILE)' != ''"> - <SignAssembly>true</SignAssembly> - <!-- If PUBLIC_KEYFILE is set we use delay sign to sign the assembly --> - <DelaySign>true</DelaySign> - <AssemblyOriginatorKeyFile Condition="'$(PUBLIC_KEYFILE)' != ''">$(PUBLIC_KEYFILE)</AssemblyOriginatorKeyFile> - - <!-- If PUBLIC_KEYFILE is not set sign the assembly using KEYFILE --> - <DelaySign Condition="'$(PUBLIC_KEYFILE)' == ''">false</DelaySign> - <AssemblyOriginatorKeyFile Condition="'$(PUBLIC_KEYFILE)' == ''">$(KEYFILE)</AssemblyOriginatorKeyFile> - </PropertyGroup> + <Import Project="$(MSBuildThisFileDirectory)/../../config/ice.common.sign.targets" /> + <PropertyGroup> + <SignTarget>$(IntermediateOutputPath)$(TargetName)$(TargetExt)</SignTarget> + </PropertyGroup> + <PropertyGroup Condition="'$(PUBLIC_KEYFILE)' != '' Or '$(KEYFILE)' != ''"> + <SignAssembly>true</SignAssembly> + <!-- If PUBLIC_KEYFILE is set we use delay sign to sign the assembly --> + <DelaySign>true</DelaySign> + <AssemblyOriginatorKeyFile Condition="'$(PUBLIC_KEYFILE)' != ''">$(PUBLIC_KEYFILE)</AssemblyOriginatorKeyFile> + + <!-- If PUBLIC_KEYFILE is not set sign the assembly using KEYFILE --> + <DelaySign Condition="'$(PUBLIC_KEYFILE)' == ''">false</DelaySign> + <AssemblyOriginatorKeyFile Condition="'$(PUBLIC_KEYFILE)' == ''">$(KEYFILE)</AssemblyOriginatorKeyFile> + </PropertyGroup> <Target Name="SignPackage" BeforeTargets="CopyFilesToOutputDirectory" - Condition="'$(OS)' == 'Windows_NT' and Exists('$(SIGN_CERTIFICATE)') and (!Exists('$(IntermediateOutputPath)sign.log') or $([System.IO.File]::GetLastWriteTime('$(IntermediateOutputPath)$(TargetName)$(TargetExt)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(IntermediateOutputPath)sign.log').Ticks))"> - <Message Text="Signing $(IntermediateOutputPath)$(TargetName)$(TargetExt)" /> + Condition="'$(OS)' == 'Windows_NT' and Exists('$(SIGN_CERTIFICATE)') and (!Exists('$(IntermediateOutputPath)sign.log') or $([System.IO.File]::GetLastWriteTime('$(SignTarget)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(IntermediateOutputPath)sign.log').Ticks))"> + <Message Text="Signing $(SignTarget)" /> <!-- If both KEYFILE and PUBLIC_KEYFILE are set we re-sign the assembly using KEYFILE after it has been build --> - <Exec Command="sn -Ra "$(IntermediateOutputPath)$(TargetName)$(TargetExt)" "$(KEYFILE)"" + <Exec Command="sn -Ra "$(SignTarget)" "$(KEYFILE)"" Condition="'$(KEYFILE)' != '' and '$(PUBLIC_KEYFILE)' != ''" /> <!-- Authenticode signing --> - <Exec Command="$(SignCommandSHA1) "$(IntermediateOutputPath)$(TargetName)$(TargetExt)"" EchoOff="yes"/> - <Exec Command="$(SignCommandSHA256) "$(IntermediateOutputPath)$(TargetName)$(TargetExt)"" EchoOff="yes" - Condition="'$(DefaultPlatformToolset)' != 'v100'"/> + <SignTask + WorkingDirectory="$(IntermediateOutputPath)" + AdditionalOptions="$(SignCommandSHA1)" + Files="$(TargetName)$(TargetExt)"/> + + <SignTask + WorkingDirectory="$(IntermediateOutputPath)" + AdditionalOptions="$(SignCommandSHA256)" + Files="$(TargetName)$(TargetExt)"/> <WriteLinesToFile File = "$(IntermediateOutputPath)sign.log" Encoding = "Unicode" Overwrite = "true" - Lines = "Signing $(IntermediateOutputPath)$(TargetName)$(TargetExt)"/> + Lines = "Signing $(SignTarget)"/> </Target> <Target Name="SignPackageClean" AfterTargets="Clean" Condition="'$(OS)' == 'Windows_NT' "> |