chromium/chrome/services/file_util/public/cpp/sandboxed_zip_analyzer_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/services/file_util/public/cpp/sandboxed_zip_analyzer.h"

#include <stdint.h>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/safe_browsing/archive_analyzer_results.h"
#include "chrome/services/file_util/fake_file_util_service.h"
#include "chrome/services/file_util/file_util_service.h"
#include "chrome/services/file_util/public/mojom/safe_archive_analyzer.mojom.h"
#include "components/safe_browsing/core/common/features.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

#if BUILDFLAG(IS_MAC)
const char kAppInZipHistogramName[] =
    "SBClientDownload.ZipFileContainsAppDirectory";
#endif  // BUILDFLAG(IS_MAC)

_;

}  // namespace

class SandboxedZipAnalyzerTest : public ::testing::Test {};

// static
const uint8_t SandboxedZipAnalyzerTest::kUnsignedDigest[] =;
const uint8_t SandboxedZipAnalyzerTest::kSignedDigest[] =;
const uint8_t SandboxedZipAnalyzerTest::kJSEFileDigest[] =;
const SandboxedZipAnalyzerTest::BinaryData
    SandboxedZipAnalyzerTest::kUnsignedExe =;
const SandboxedZipAnalyzerTest::BinaryData
    SandboxedZipAnalyzerTest::kSignedExe =;
const SandboxedZipAnalyzerTest::BinaryData SandboxedZipAnalyzerTest::kJSEFile =;

#if BUILDFLAG(IS_MAC)
const uint8_t SandboxedZipAnalyzerTest::kUnsignedMachODigest[] = {
    0xe4, 0x62, 0xff, 0x75, 0x2f, 0xf9, 0xd8, 0x4e, 0x34, 0xd8, 0x43,
    0xe5, 0xd4, 0x6e, 0x20, 0x12, 0xad, 0xcb, 0xd4, 0x85, 0x40, 0xa8,
    0x47, 0x3f, 0xb7, 0x94, 0xb2, 0x86, 0xa3, 0x89, 0xb9, 0x45};
const SandboxedZipAnalyzerTest::BinaryData
    SandboxedZipAnalyzerTest::kUnsignedMachO = {
        "app-with-executables.app/Contents/MacOS/executablefat",
        safe_browsing::ClientDownloadRequest_DownloadType_WIN_EXECUTABLE,
        &kUnsignedMachODigest[0],
        16640,
        false,  // !is_signed
};
const uint8_t SandboxedZipAnalyzerTest::kSignedMachODigest[] = {
    0x59, 0x0b, 0xc9, 0xc8, 0xee, 0x6c, 0xec, 0x94, 0x46, 0xc1, 0x44,
    0xd8, 0xea, 0x2b, 0x10, 0x85, 0xb1, 0x5b, 0x5c, 0x68, 0x80, 0x9b,
    0x2c, 0x27, 0x48, 0xad, 0x04, 0x0c, 0x2a, 0x1e, 0xf8, 0x29};
const SandboxedZipAnalyzerTest::BinaryData
    SandboxedZipAnalyzerTest::kSignedMachO = {
        "app-with-executables.app/Contents/MacOS/signedexecutablefat",
        safe_browsing::ClientDownloadRequest_DownloadType_WIN_EXECUTABLE,
        &kSignedMachODigest[0],
        34176,
        true,  // !is_signed
};
#endif  // BUILDFLAG(IS_MAC)

TEST_F(SandboxedZipAnalyzerTest, NoBinaries) {}

TEST_F(SandboxedZipAnalyzerTest, OneUnsignedBinary) {}

TEST_F(SandboxedZipAnalyzerTest, TwoBinariesOneSigned) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedArchiveNoBinaries) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedNestedArchive) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedTooManyNestedArchive) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedRarArchiveNoBinaries) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedArchiveAndBinaries) {}

TEST_F(SandboxedZipAnalyzerTest,
       ZippedArchiveAndBinariesWithTrailingSpaceAndPeriodChars) {}

TEST_F(SandboxedZipAnalyzerTest, ZippedJSEFile) {}

TEST_F(SandboxedZipAnalyzerTest, EncryptedZip) {}

TEST_F(SandboxedZipAnalyzerTest, EncryptedZipWrongPassword) {}

TEST_F(SandboxedZipAnalyzerTest, EncryptedZipAes) {}

TEST_F(SandboxedZipAnalyzerTest, EncryptedZipAesNoPassword) {}

#if BUILDFLAG(IS_MAC)
TEST_F(SandboxedZipAnalyzerTest, ZippedAppWithUnsignedAndSignedExecutable) {
  base::HistogramTester histograms;
  histograms.ExpectTotalCount(kAppInZipHistogramName, 0);

  safe_browsing::ArchiveAnalyzerResults results;
  RunAnalyzer(dir_test_data_.AppendASCII(
                  "mach_o/zipped-app-two-executables-one-signed.zip"),
              &results);

  EXPECT_TRUE(results.success);
  EXPECT_TRUE(results.has_executable);
  EXPECT_FALSE(results.has_archive);

  // Many of the files within the app have no extension, and are therefore
  // flagged by Safe Browsing. So search for the two executables.
  bool found_unsigned = false;
  bool found_signed = false;
  for (const auto& binary : results.archived_binary) {
    if (kSignedMachO.file_path == binary.file_path()) {
      found_signed = true;
      ExpectBinary(kSignedMachO, binary);
    }

    if (kUnsignedMachO.file_path == binary.file_path()) {
      found_unsigned = true;
      ExpectBinary(kUnsignedMachO, binary);
    }
  }

  if (!found_unsigned || !found_signed) {
    LOG(ERROR) << "Expected to find: " << kSignedMachO.file_path << " and "
               << kUnsignedMachO.file_path;
    for (const auto& binary : results.archived_binary) {
      LOG(ERROR) << "Found " << binary.file_path();
    }
  }
  EXPECT_TRUE(found_unsigned);
  EXPECT_TRUE(found_signed);
}
#endif  // BUILDFLAG(IS_MAC)

TEST_F(SandboxedZipAnalyzerTest, CanDeleteDuringExecution) {}

TEST_F(SandboxedZipAnalyzerTest, InvalidPath) {}

TEST_F(SandboxedZipAnalyzerTest, NestedEncryptedZip) {}

TEST_F(SandboxedZipAnalyzerTest, NestedEncryptedRar) {}