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

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: Created 5 years, 2 months 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..4f2831dd33540668e3b40d280a2ece5d3b79cfc3
--- /dev/null
+++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc
@@ -0,0 +1,145 @@
+// 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_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) {
+ FILE* file = base::OpenFile(file_path, "r+");
Robert Sesek 2015/10/05 22:19:07 base/files/file.h is probably a better interface t
Greg K 2015/10/07 22:54:29 Done.
+
+ if (file == NULL)
+ return false;
+
+ if (fseek(file, 0x1F90, SEEK_SET) == -1)
+ return false;
+
+ char vec[] = {0xAA};
+ size_t written = fwrite(vec, sizeof(char), 1, file);
+ return base::CloseFile(file) && written == sizeof(char);
+}
+} // namespace
+
+class BinaryIntegrityAnalyzerMacTest : public ::testing::Test {
+ public:
+ BinaryIntegrityAnalyzerMacTest();
+
+ protected:
+ base::FilePath test_data_dir_;
+ scoped_ptr<base::ScopedPathOverride> exe_dir_override_;
+ scoped_ptr<base::ScopedPathOverride> exe_override_;
+ base::ScopedTempDir temp_dir_;
+};
+
+BinaryIntegrityAnalyzerMacTest::BinaryIntegrityAnalyzerMacTest() {
+ // Retrieve DIR_TEST_DATA here because it is based on DIR_EXE and we are
+ // about to override the path to the latter.
+ CHECK(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
Robert Sesek 2015/10/05 22:19:07 Don't CHECK in tests. Use ASSERT_TRUE instead.
Greg K 2015/10/07 22:54:29 Done.
+ test_data_dir_ = test_data_dir_.Append("safe_browsing/mach_o/");
+
+ // Set up the temp directory to copy the bundle to.
+ CHECK(temp_dir_.CreateUniqueTempDir());
Robert Sesek 2015/10/05 22:19:07 Same, no CHECK.
Greg K 2015/10/07 22:54:29 Done.
+ base::FilePath exe_path = temp_dir_.path().AppendASCII(kBundleURL);
+
+ // Copy the signed bundle to the temp directory.
+ base::FilePath signed_bundle_path(test_data_dir_);
+ signed_bundle_path = signed_bundle_path.Append(kBundleBase);
Robert Sesek 2015/10/05 22:19:07 It's typical to chain the Append calls: base::F
Greg K 2015/10/07 22:54:29 Done.
+ base::FilePath copied_bundle_path(temp_dir_.path());
+ copied_bundle_path = copied_bundle_path.Append(kBundleBase);
+ CHECK(base::CopyDirectory(signed_bundle_path, copied_bundle_path, true));
Robert Sesek 2015/10/05 22:19:07 No CHECK.
Greg K 2015/10/07 22:54:29 Done.
+
+ // 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, VerifyBinaryIntegrityHelper) {
+ 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\"");
+ VerifyBinaryIntegrityHelper(mock_receiver.Pass(), exe, requirement);
+
+ base::FilePath exe_path;
+ ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe_path));
+ ASSERT_TRUE(CorruptFileContent(exe_path));
+
+ mock_receiver.reset(new MockIncidentReceiver());
+ scoped_ptr<Incident> incident;
+ EXPECT_CALL(*mock_receiver, DoAddIncidentForProcess(_))
+ .WillOnce(TakeIncident(&incident));
+
+ VerifyBinaryIntegrityHelper(mock_receiver.Pass(), exe, requirement);
Greg K 2015/10/07 22:54:29 This should be .get()
+
+ // Verify that theincident report contains the expected data.
+ scoped_ptr<ClientIncidentReport_IncidentData> incident_data(
+ incident->TakePayload());
+
+ ASSERT_TRUE(incident_data->has_osx_incident());
+ ASSERT_TRUE(incident_data->osx_incident().has_file_basename());
+ ASSERT_EQ("test-bundle", incident_data->osx_incident().file_basename());
+ ASSERT_TRUE(incident_data->osx_incident().has_sec_error());
+ ASSERT_EQ(-67061, incident_data->osx_incident().sec_error());
+ ASSERT_EQ(1, incident_data->osx_incident().sub_incident_size());
+
+ const auto& sub_incident = incident_data->osx_incident().sub_incident(0);
+ ASSERT_TRUE(sub_incident.has_file_basename());
+ ASSERT_EQ("test-bundle", sub_incident.file_basename());
+ ASSERT_TRUE(sub_incident.has_signature());
+ ASSERT_TRUE(sub_incident.signature().signed_data_size() > 0);
+}
+
+} // namespace safe_browsing

Powered by Google App Engine
This is Rietveld 408576698