Skip to content

Commit

Permalink
Merge pull request #9 from Microsoft/dev/lukaszme/mark_of_the_web
Browse files Browse the repository at this point in the history
Check Mark of the Web on the binaries during discovery
  • Loading branch information
Łukasz Mendakiewicz authored Jul 25, 2017
2 parents f945ee2 + 872cbd4 commit d0683a7
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 15 deletions.
30 changes: 25 additions & 5 deletions GoogleTestAdapter/Core/GoogleTestDiscoverer.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
// This file has been modified by Microsoft on 7/2017.

using GoogleTestAdapter.Common;
using GoogleTestAdapter.DiaResolver;
using GoogleTestAdapter.Framework;
using GoogleTestAdapter.Helpers;
using GoogleTestAdapter.Model;
using GoogleTestAdapter.Settings;
using GoogleTestAdapter.TestCases;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Text.RegularExpressions;

namespace GoogleTestAdapter
{
Expand Down Expand Up @@ -46,6 +49,9 @@ public void DiscoverTests(IEnumerable<string> executables, ITestFrameworkReporte
{
_settings.ExecuteWithSettingsForExecutable(executable, () =>
{
if (!VerifyExecutableTrust(executable, _logger))
return;

IList<TestCase> testCases = GetTestsFromExecutable(executable);
reporter.ReportTestsFound(testCases);
}, _logger);
Expand All @@ -57,6 +63,9 @@ private static void DiscoverTests(string executable, ITestFrameworkReporter repo
{
settings.ExecuteWithSettingsForExecutable(executable, () =>
{
if (!VerifyExecutableTrust(executable, logger))
return;

int nrOfTestCases = 0;
Action<TestCase> reportTestCases = tc =>
{
Expand Down Expand Up @@ -146,6 +155,17 @@ private bool SafeMatches(string executable, string regex)
return matches;
}

private static bool VerifyExecutableTrust(string executable, ILogger logger)
{
var zone = Zone.CreateFromUrl(executable);
if (zone.SecurityZone != System.Security.SecurityZone.MyComputer)
{
logger.LogError("Executable " + executable + " came from another computer and was blocked to help protect this computer.");
return false;
}
return true;
}

}

}
18 changes: 17 additions & 1 deletion GoogleTestAdapter/GoogleTestAdapter.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26606.0
VisualStudioVersion = 15.0.26717.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1F754A4D-BD42-4368-8B90-F3C03F24A2F3}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -128,6 +128,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packaging.GTA", "Packaging.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packaging.TAfGT", "Packaging.TAfGT\Packaging.TAfGT.csproj", "{B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SemaphoreExe", "SemaphoreExe\SemaphoreExe.vcxproj", "{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
VsPackage.Shared\VsPackage.Shared.projitems*{55294b5f-a075-43f2-b0e9-2b11925e8b91}*SharedItemsImports = 4
Expand Down Expand Up @@ -487,6 +489,16 @@ Global
{B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x64.Build.0 = Release|Any CPU
{B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x86.ActiveCfg = Release|Any CPU
{B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x86.Build.0 = Release|Any CPU
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|Any CPU.ActiveCfg = Debug|Win32
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|x64.ActiveCfg = Debug|x64
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|x64.Build.0 = Debug|x64
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|x86.ActiveCfg = Debug|Win32
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|x86.Build.0 = Debug|Win32
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Release|Any CPU.ActiveCfg = Release|Win32
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Release|x64.ActiveCfg = Release|x64
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Release|x64.Build.0 = Release|x64
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Release|x86.ActiveCfg = Release|Win32
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -514,5 +526,9 @@ Global
{72AEA89D-FA32-4E4F-BA04-9C670B53F746} = {475245AA-A07D-41D8-BC84-959C5E12A52C}
{BAB53542-85AA-4780-9F48-2984C036189A} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC}
{2E3221EB-86DA-427D-84EC-DEFD3F966D9A} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC}
{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43} = {475245AA-A07D-41D8-BC84-959C5E12A52C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C942DDD5-B04E-4D57-BA9F-A444392C9480}
EndGlobalSection
EndGlobal
7 changes: 7 additions & 0 deletions GoogleTestAdapter/SemaphoreExe/SemaphoreExe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <cstdio>

int main()
{
fclose(fopen("SemaphoreExe.sem", "w"));
return 143;
}
42 changes: 42 additions & 0 deletions GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SemaphoreExe</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Common.props))\Common.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ItemGroup>
<ClCompile Include="SemaphoreExe.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
99 changes: 90 additions & 9 deletions GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
// This file has been modified by Microsoft on 7/2017.

using FluentAssertions;
using GoogleTestAdapter.Helpers;
using GoogleTestAdapter.Tests.Common;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Win32.SafeHandles;
using Moq;
using GoogleTestAdapter.Helpers;
using GoogleTestAdapter.Tests.Common;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories;

namespace GoogleTestAdapter.TestAdapter
Expand Down Expand Up @@ -32,17 +39,81 @@ public void DiscoverTests_WithCustomNonMatchingRegex_DoesNotFindTests()
[TestCategory(Integration)]
public void DiscoverTests_CrashingExecutable_CrashIsLogged()
{
RunExecutableAndCheckLogging(TestResources.AlwaysCrashingExe);
RunExecutableAndCheckLogging(TestResources.AlwaysCrashingExe,
() => MockLogger.Verify(l => l.LogError(It.Is<string>(s => s.Contains("Could not list test cases of executable"))),
Times.Once));
}

[TestMethod]
[TestCategory(Integration)]
public void DiscoverTests_FailingExecutable_ExitCodeIsLogged()
{
RunExecutableAndCheckLogging(TestResources.AlwaysFailingExe);
RunExecutableAndCheckLogging(TestResources.AlwaysFailingExe,
() => MockLogger.Verify(l => l.LogError(It.Is<string>(s => s.Contains("executing process failed with return code 4711"))),
Times.Once));
}

private void MarkUntrusted(string path)
{
using (var handle = NativeMethods.CreateFileW(path + ":Zone.Identifier", NativeMethods.GENERIC_WRITE, 0, IntPtr.Zero,
NativeMethods.CREATE_NEW, 0, IntPtr.Zero))
{
if (handle.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}

using (var stream = new FileStream(handle, FileAccess.Write))
{
var data = Encoding.ASCII.GetBytes("[ZoneTransfer]\r\nZoneId=3");
stream.Write(data, 0, data.Length);
}
}
}

[TestMethod]
[TestCategory(Integration)]
public void DiscoverTests_UntrustedExecutable_IsNotRun()
{
var SemPath = Path.Combine(Directory.GetCurrentDirectory(), "SemaphoreExe.sem");
var Temp1Exe = Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "Temp1.exe");
var Temp2Exe = Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "Temp2.exe");

// Verify baseline
try
{
File.Copy(TestResources.SemaphoreExe, Temp1Exe);
File.Exists(SemPath).Should().BeFalse();
RunExecutableAndCheckLogging(Temp1Exe,
() => MockLogger.Verify(l => l.LogError(It.Is<string>(s => s.Contains("executing process failed with return code 143"))),
Times.Once));
File.Exists(SemPath).Should().BeTrue("because exe should have been run");
}
finally
{
File.Delete(SemPath);
File.Delete(Temp1Exe);
}

// Verify untrusted exe is not run
try
{
File.Copy(TestResources.SemaphoreExe, Temp2Exe);
MarkUntrusted(Temp2Exe);
File.Exists(SemPath).Should().BeFalse();
RunExecutableAndCheckLogging(Temp2Exe,
() => MockLogger.Verify(l => l.LogError(It.Is<string>(s => s.Contains("was blocked to help protect"))),
Times.Once));
File.Exists(SemPath).Should().BeFalse("because exe should not have been run");
}
finally
{
File.Delete(SemPath);
File.Delete(Temp2Exe);
}
}

private void RunExecutableAndCheckLogging(string executable)
private void RunExecutableAndCheckLogging(string executable, Action verify)
{
var mockDiscoveryContext = new Mock<IDiscoveryContext>();
var mockDiscoverySink = new Mock<ITestCaseDiscoverySink>();
Expand All @@ -53,8 +124,7 @@ private void RunExecutableAndCheckLogging(string executable)
discoverer.DiscoverTests(executable.Yield(), mockDiscoveryContext.Object, mockVsLogger.Object,
mockDiscoverySink.Object);

MockLogger.Verify(l => l.LogError(It.Is<string>(s => s.Contains("Could not list test cases of executable"))),
Times.Once);
verify();
}

private void CheckForDiscoverySinkCalls(int expectedNrOfTests, string customRegex = null)
Expand Down Expand Up @@ -83,4 +153,15 @@ private void CheckForDiscoverySinkCalls(int expectedNrOfTests, string customRege

}

static class NativeMethods
{
public const int GENERIC_WRITE = 1073741824;
public const int CREATE_NEW = 1;

[DllImport("kernel32.dll")]
public static extern SafeFileHandle CreateFileW(
[MarshalAs(UnmanagedType.LPWStr)] string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition,uint dwFlagsAndAttributes, IntPtr hTemplateFile);
}

}
1 change: 1 addition & 0 deletions GoogleTestAdapter/Tests.Common/TestResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static class TestResources
public const string TenSecondsWaiter = GoogleTestAdapterBuildDir + @"TenSecondsWaiter\TenSecondsWaiter.exe";
public const string AlwaysCrashingExe = GoogleTestAdapterBuildDir + @"CrashingExe\CrashingExe.exe";
public const string AlwaysFailingExe = GoogleTestAdapterBuildDir + @"FailingExe\FailingExe.exe";
public const string SemaphoreExe = GoogleTestAdapterBuildDir + @"SemaphoreExe\SemaphoreExe.exe";

public const string Tests_DebugX86 = SampleTestsBuildDir + @"Debug\Tests_gta.exe";
public const string Tests_ReleaseX86 = SampleTestsBuildDir + @"Release\Tests_gta.exe";
Expand Down

0 comments on commit d0683a7

Please sign in to comment.