Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5652)

Unified Diff: chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc

Issue 1363613004: Implement anonymous, opt-in, collection of OS X binary integrity incidents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ran git cl format Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..8d3c00ae639264196edf9cbafc2dfdc672dece4e
--- /dev/null
+++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc
@@ -0,0 +1,139 @@
+// 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_mac.h"
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/mac/bundle_locations.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.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_;
+ base::ScopedTempDir temp_dir_;
+};
+
+void BinaryIntegrityAnalyzerMacTest::SetUp() {
+ 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());
+
+ // 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));
+}
+
+TEST_F(BinaryIntegrityAnalyzerMacTest, GetCriticalPathsAndRequirements) {
+ // Expected paths and requirement strings.
+ std::vector<PathAndRequirement> paths_and_requirements_expected;
+
+ 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(
+ PathAndRequirement(base::mac::OuterBundlePath(), expected_req));
+
+ std::vector<PathAndRequirement> paths_and_requirements =
+ GetCriticalPathsAndRequirements();
+ ASSERT_EQ(1u, paths_and_requirements.size());
+ EXPECT_EQ(paths_and_requirements[0].path,
+ paths_and_requirements_expected[0].path);
+ EXPECT_EQ(paths_and_requirements[0].requirement,
+ paths_and_requirements_expected[0].requirement);
+}
+
+TEST_F(BinaryIntegrityAnalyzerMacTest, VerifyBinaryIntegrityForTesting) {
+ scoped_ptr<MockIncidentReceiver> mock_receiver(
+ new StrictMock<MockIncidentReceiver>());
+ base::FilePath bundle = temp_dir_.path().Append(kBundleBase);
+ std::string requirement(
+ "certificate leaf[subject.CN]=\"untrusted@goat.local\"");
+
+ // Run check on valid bundle.
+ scoped_ptr<Incident> incident_to_clear;
+ EXPECT_CALL(*mock_receiver, DoClearIncidentForProcess(_))
+ .WillOnce(TakeIncident(&incident_to_clear));
+ VerifyBinaryIntegrityForTesting(mock_receiver.get(), bundle, requirement);
+
+ ASSERT_TRUE(incident_to_clear);
+ ASSERT_EQ(IncidentType::BINARY_INTEGRITY, incident_to_clear->GetType());
+ ASSERT_EQ(incident_to_clear->GetKey(), "test-bundle.app");
+
+ base::FilePath exe_path = temp_dir_.path().Append(kBundleURL);
+ ASSERT_TRUE(CorruptFileContent(exe_path));
+
+ scoped_ptr<Incident> incident;
+ EXPECT_CALL(*mock_receiver, DoAddIncidentForProcess(_))
+ .WillOnce(TakeIncident(&incident));
+
+ VerifyBinaryIntegrityForTesting(mock_receiver.get(), bundle, 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());
+ EXPECT_TRUE(incident_data->binary_integrity().has_file_basename());
+ EXPECT_EQ("test-bundle.app",
+ incident_data->binary_integrity().file_basename());
+ EXPECT_TRUE(incident_data->binary_integrity().has_sec_error());
+ EXPECT_EQ(-67061, incident_data->binary_integrity().sec_error());
+ EXPECT_FALSE(incident_data->binary_integrity().has_signature());
+ EXPECT_EQ(0,
+ incident_data->binary_integrity().signature().signed_data_size());
+ EXPECT_EQ(1, incident_data->binary_integrity().contained_file_size());
+
+ const auto& contained_file =
+ incident_data->binary_integrity().contained_file(0);
+ EXPECT_EQ(contained_file.relative_path(), "Contents/MacOS/test-bundle");
+ EXPECT_TRUE(contained_file.has_signature());
+ EXPECT_TRUE(contained_file.has_image_headers());
+}
+
+} // namespace safe_browsing

Powered by Google App Engine
This is Rietveld 408576698