Chromium Code Reviews| Index: chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc |
| diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8a01158e153dd55a5cdb90c0678bfd47985360bc |
| --- /dev/null |
| +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc |
| @@ -0,0 +1,140 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h" |
| + |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| + |
| +#include "base/bind.h" |
| +#include "base/files/file.h" |
| +#include "base/files/file_util.h" |
| +#include "base/files/scoped_temp_dir.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/path_service.h" |
| +#include "base/test/scoped_path_override.h" |
| +#include "chrome/browser/safe_browsing/incident_reporting/incident.h" |
| +#include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" |
| +#include "chrome/common/chrome_paths.h" |
| +#include "chrome/common/safe_browsing/csd.pb.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::_; |
| +using ::testing::StrictMock; |
| + |
| +namespace safe_browsing { |
| + |
| +namespace { |
| + |
| +const char kBundleBase[] = "test-bundle.app"; |
| +const char kBundleURL[] = "test-bundle.app/Contents/MacOS/test-bundle"; |
| + |
| +// Helper function to corrupt the content of a binary to make sure the signature |
| +// verification will fail. |
| +bool CorruptFileContent(const base::FilePath& file_path) { |
| + // This is the hard coded position of the TEXT segment in the mach-o file. |
| + static const uint64_t text_pos = 0x1F90; |
| + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_WRITE); |
| + if (!file.IsValid()) |
| + return false; |
| + char vec[] = {0xAA}; |
| + return file.Write(text_pos, vec, sizeof(vec)) == sizeof(vec); |
| +} |
| + |
| +} // namespace |
| + |
| +class BinaryIntegrityAnalyzerMacTest : public ::testing::Test { |
| + public: |
| + void SetUp() override; |
| + |
| + protected: |
| + base::FilePath test_data_dir_; |
| + scoped_ptr<base::ScopedPathOverride> exe_dir_override_; |
| + scoped_ptr<base::ScopedPathOverride> exe_override_; |
| + base::ScopedTempDir temp_dir_; |
| +}; |
| + |
| +void BinaryIntegrityAnalyzerMacTest::SetUp() { |
| + // Retrieve DIR_TEST_DATA here because it is based on DIR_EXE and we are |
| + // about to override the path to the latter. |
| + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); |
| + test_data_dir_ = test_data_dir_.Append("safe_browsing/mach_o/"); |
| + |
| + // Set up the temp directory to copy the bundle to. |
| + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| + base::FilePath exe_path = temp_dir_.path().AppendASCII(kBundleURL); |
| + |
| + // Copy the signed bundle to the temp directory. |
| + base::FilePath signed_bundle_path = |
| + base::FilePath(test_data_dir_).Append(kBundleBase); |
| + base::FilePath copied_bundle_path = |
| + base::FilePath(temp_dir_.path()).Append(kBundleBase); |
| + ASSERT_TRUE( |
| + base::CopyDirectory(signed_bundle_path, copied_bundle_path, true)); |
| + |
| + // Now setup the path service overrides. |
| + exe_dir_override_.reset( |
| + new base::ScopedPathOverride(base::DIR_EXE, temp_dir_.path())); |
| + exe_override_.reset(new base::ScopedPathOverride(base::FILE_EXE, exe_path)); |
| +} |
| + |
| +TEST_F(BinaryIntegrityAnalyzerMacTest, GetCriticalPathsAndRequirements) { |
| + // Expected paths and requirement strings. |
| + std::vector<std::pair<base::FilePath, std::string>> |
| + paths_and_requirements_expected; |
| + |
| + base::FilePath exe_path = temp_dir_.path().AppendASCII(kBundleURL); |
| + char resolved_name[PATH_MAX]; |
| + ASSERT_NE(realpath(exe_path.value().c_str(), resolved_name), nullptr); |
| + |
| + std::string expected_req = |
| + "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] " |
| + "exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and " |
| + "certificate leaf[subject.OU]=\"EQHXZ8M8AV\" and " |
| + "(identifier=\"com.google.Chrome\" or " |
| + "identifier=\"com.google.Chrome.canary\")"; |
| + paths_and_requirements_expected.push_back( |
| + std::make_pair(std::string(resolved_name), expected_req)); |
| + |
| + std::vector<std::pair<base::FilePath, std::string>> paths_and_requirements = |
| + GetCriticalPathsAndRequirements(); |
| + ASSERT_THAT(paths_and_requirements, |
| + ::testing::ContainerEq(paths_and_requirements_expected)); |
| +} |
| + |
| +TEST_F(BinaryIntegrityAnalyzerMacTest, VerifyBinaryIntegrityForTesting) { |
| + scoped_ptr<MockIncidentReceiver> mock_receiver( |
| + new StrictMock<MockIncidentReceiver>()); |
| + base::FilePath exe; |
| + ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe)); |
| + std::string requirement( |
| + "certificate leaf[subject.CN]=\"untrusted@goat.local\""); |
| + VerifyBinaryIntegrityForTesting(mock_receiver.get(), exe, requirement); |
| + |
| + base::FilePath exe_path; |
| + ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe_path)); |
| + ASSERT_TRUE(CorruptFileContent(exe_path)); |
| + |
| + scoped_ptr<Incident> incident; |
| + EXPECT_CALL(*mock_receiver, DoAddIncidentForProcess(_)) |
| + .WillOnce(TakeIncident(&incident)); |
| + |
| + VerifyBinaryIntegrityForTesting(mock_receiver.get(), exe, requirement); |
| + |
| + // Verify that the incident report contains the expected data. |
| + scoped_ptr<ClientIncidentReport_IncidentData> incident_data( |
| + incident->TakePayload()); |
| + |
| + ASSERT_TRUE(incident_data->has_binary_integrity()); |
|
Robert Sesek
2015/10/08 19:20:06
These can be EXPECT_ variants. The difference is t
Greg K
2015/10/09 17:12:01
Done.
|
| + ASSERT_TRUE(incident_data->binary_integrity().has_file_basename()); |
| + ASSERT_EQ("test-bundle", incident_data->binary_integrity().file_basename()); |
| + ASSERT_TRUE(incident_data->binary_integrity().has_sec_error()); |
| + ASSERT_EQ(-67061, incident_data->binary_integrity().sec_error()); |
| + ASSERT_TRUE(incident_data->binary_integrity().has_signature()); |
| + ASSERT_TRUE(incident_data->binary_integrity().signature().signed_data_size() > |
|
Robert Sesek
2015/10/08 19:20:06
EXPECT_GT
Greg K
2015/10/09 17:12:01
Done.
|
| + 0); |
| +} |
| + |
| +} // namespace safe_browsing |