Commit ad471a32 authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

Move IsFileQuarantined() to a test-only build target

This will simplify future refactoring where QuarantineFile() is moved to
an OOP service but not IsFileQuarantined().

This CL includes no functional change.

Bug: 870998
Change-Id: Ic30bf70b119e37de88baa374a4791678df80d393
Reviewed-on: https://chromium-review.googlesource.com/1228782Reviewed-by: default avatarAsanka Herath <asanka@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592963}
parent efacae11
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
#include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h" #include "components/download/public/common/download_item.h"
#include "components/download/quarantine/quarantine.h" #include "components/download/quarantine/test_support.h"
#include "components/history/content/browser/download_conversions.h" #include "components/history/content/browser/download_conversions.h"
#include "components/history/core/browser/download_constants.h" #include "components/history/core/browser/download_constants.h"
#include "components/history/core/browser/download_row.h" #include "components/history/core/browser/download_row.h"
......
...@@ -1014,7 +1014,7 @@ test("browser_tests") { ...@@ -1014,7 +1014,7 @@ test("browser_tests") {
"//components/dom_distiller/content/browser", "//components/dom_distiller/content/browser",
"//components/dom_distiller/content/renderer", "//components/dom_distiller/content/renderer",
"//components/dom_distiller/core:test_support", "//components/dom_distiller/core:test_support",
"//components/download/quarantine", "//components/download/quarantine:test_support",
"//components/feature_engagement/test:test_support", "//components/feature_engagement/test:test_support",
"//components/offline_items_collection/core/test_support", "//components/offline_items_collection/core/test_support",
"//components/optimization_guide:test_support", "//components/optimization_guide:test_support",
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/test/ppapi/ppapi_test.h" #include "chrome/test/ppapi/ppapi_test.h"
#include "chrome/test/ppapi/ppapi_test_select_file_dialog_factory.h" #include "chrome/test/ppapi/ppapi_test_select_file_dialog_factory.h"
#include "components/download/quarantine/quarantine.h" #include "components/download/quarantine/test_support.h"
#include "ppapi/shared_impl/test_utils.h" #include "ppapi/shared_impl/test_utils.h"
#if defined(FULL_SAFE_BROWSING) #if defined(FULL_SAFE_BROWSING)
......
...@@ -12,7 +12,6 @@ static_library("quarantine") { ...@@ -12,7 +12,6 @@ static_library("quarantine") {
sources = [ sources = [
"quarantine.cc", "quarantine.cc",
"quarantine.h", "quarantine.h",
"quarantine_constants_linux.h",
"quarantine_features_win.cc", "quarantine_features_win.cc",
"quarantine_features_win.h", "quarantine_features_win.h",
"quarantine_linux.cc", "quarantine_linux.cc",
...@@ -21,6 +20,7 @@ static_library("quarantine") { ...@@ -21,6 +20,7 @@ static_library("quarantine") {
] ]
deps = [ deps = [
":common",
"//base", "//base",
"//net", "//net",
"//url", "//url",
...@@ -34,8 +34,57 @@ static_library("quarantine") { ...@@ -34,8 +34,57 @@ static_library("quarantine") {
} }
} }
source_set("common") {
sources = [
"common_linux.cc",
"common_linux.h",
"common_mac.h",
"common_mac.mm",
"common_win.cc",
"common_win.h",
]
deps = [
"//base",
]
if (is_mac) {
libs = [
"Carbon.framework",
"Foundation.framework",
]
}
}
source_set("test_support") {
testonly = true
sources = [
"test_support.cc",
"test_support.h",
"test_support_linux.cc",
"test_support_mac.mm",
"test_support_win.cc",
]
deps = [
":common",
":quarantine",
"//base",
"//url",
]
if (is_mac) {
libs = [
"Carbon.framework",
"Foundation.framework",
]
}
}
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [
"quarantine_linux_unittest.cc", "quarantine_linux_unittest.cc",
"quarantine_mac_unittest.mm", "quarantine_mac_unittest.mm",
...@@ -51,11 +100,20 @@ source_set("unit_tests") { ...@@ -51,11 +100,20 @@ source_set("unit_tests") {
} }
deps = [ deps = [
":common",
":quarantine", ":quarantine",
":test_support",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//net", "//net",
"//testing/gtest", "//testing/gtest",
"//url", "//url",
] ]
if (is_mac) {
libs = [
"Carbon.framework",
"Foundation.framework",
]
}
} }
include_rules = [ include_rules = [
"+net/base/filename_util.h", "+net/base/filename_util.h",
] ]
\ No newline at end of file
// Copyright 2018 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 "components/download/quarantine/common_linux.h"
namespace download {
const char kSourceURLExtendedAttrName[] = "user.xdg.origin.url";
const char kReferrerURLExtendedAttrName[] = "user.xdg.referrer.url";
} // namespace download
// Copyright 2016 The Chromium Authors. All rights reserved. // Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_ #ifndef COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
#define COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_ #define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
namespace download { namespace download {
...@@ -18,4 +18,4 @@ extern const char kReferrerURLExtendedAttrName[]; ...@@ -18,4 +18,4 @@ extern const char kReferrerURLExtendedAttrName[];
} // namespace download } // namespace download
#endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_ #endif // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
// Copyright 2018 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.
#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
#define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
#import <Foundation/Foundation.h>
#include "base/mac/scoped_nsobject.h"
namespace base {
class FilePath;
}
namespace download {
bool GetQuarantinePropertiesDeprecated(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties);
bool GetQuarantineProperties(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties);
} // namespace download
#endif // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
// Copyright 2018 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 "components/download/quarantine/common_mac.h"
#import <ApplicationServices/ApplicationServices.h>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/mac/availability.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
namespace download {
// Once Chrome no longer supports macOS 10.9, this code will no longer be
// necessary. Note that LSCopyItemAttribute was deprecated in macOS 10.8, but
// the replacement to kLSItemQuarantineProperties did not exist until macOS
// 10.10.
#if !defined(MAC_OS_X_VERSION_10_10) || \
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
bool GetQuarantinePropertiesDeprecated(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties) {
const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
FSRef file_ref;
if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
return false;
base::ScopedCFTypeRef<CFTypeRef> quarantine_properties;
OSStatus status =
LSCopyItemAttribute(&file_ref, kLSRolesAll, kLSItemQuarantineProperties,
quarantine_properties.InitializeInto());
if (status != noErr)
return true;
CFDictionaryRef quarantine_properties_dict =
base::mac::CFCast<CFDictionaryRef>(quarantine_properties.get());
if (!quarantine_properties_dict) {
LOG(WARNING) << "kLSItemQuarantineProperties is not a dictionary on file "
<< file.value();
return false;
}
properties->reset(
[base::mac::CFToNSCast(quarantine_properties_dict) mutableCopy]);
return true;
}
#pragma clang diagnostic pop
#endif
API_AVAILABLE(macos(10.10))
bool GetQuarantineProperties(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties) {
base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
if (!file_url)
return false;
NSError* error = nil;
id quarantine_properties = nil;
BOOL success = [file_url getResourceValue:&quarantine_properties
forKey:NSURLQuarantinePropertiesKey
error:&error];
if (!success) {
std::string error_message(error ? error.description.UTF8String : "");
LOG(WARNING) << "Unable to get quarantine attributes for file "
<< file.value() << ". Error: " << error_message;
return false;
}
if (!quarantine_properties)
return true;
NSDictionary* quarantine_properties_dict =
base::mac::ObjCCast<NSDictionary>(quarantine_properties);
if (!quarantine_properties_dict) {
LOG(WARNING) << "Quarantine properties have wrong class: "
<< base::SysNSStringToUTF8(
[[quarantine_properties class] description]);
return false;
}
properties->reset([quarantine_properties_dict mutableCopy]);
return true;
}
} // namespace download
// Copyright 2018 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 "components/download/quarantine/common_win.h"
namespace download {
// [MS-FSCC] Section 5.6.1
const base::FilePath::CharType kZoneIdentifierStreamSuffix[] =
FILE_PATH_LITERAL(":Zone.Identifier");
} // namespace download
// Copyright 2018 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.
#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
#define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
#include "base/files/file_path.h"
namespace download {
extern const base::FilePath::CharType kZoneIdentifierStreamSuffix[];
} // namespace download
#endif // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
...@@ -17,12 +17,6 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, ...@@ -17,12 +17,6 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
return QuarantineFileResult::OK; return QuarantineFileResult::OK;
} }
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
return false;
}
} // namespace download } // namespace download
#endif // !WIN && !MAC && !LINUX #endif // !WIN && !MAC && !LINUX
...@@ -76,29 +76,6 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, ...@@ -76,29 +76,6 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
const GURL& referrer_url, const GURL& referrer_url,
const std::string& client_guid); const std::string& client_guid);
// Determine if a file has quarantine metadata attached to it.
//
// If |source_url| is non-empty, then the download source URL in
// quarantine metadata should match |source_url| exactly. The function returns
// |false| if there is a mismatch. If |source_url| is empty, then this function
// only checks for the existence of a download source URL in quarantine
// metadata.
//
// If |referrer_url| is valid, then the download referrer URL in quarantine
// metadata must match |referrer_url| exactly. The function returns |false| if
// there is a mismatch in the |referrer_url| even if the |source_url| matches.
// No referrer URL checks are performed if |referrer_url| is empty.
//
// If both |source_url| and |referrer_url|, then the funciton returns true if
// any quarantine metadata is present for the file.
//
// **Note**: On Windows, this function only checks if the |ZoneIdentifier|
// metadata is present. |source_url| and |referrer_url| are ignored. Windows
// currently doesn't store individual URLs as part of the mark-of-the-web.
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url);
} // namespace download } // namespace download
#endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_H_ #endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_H_
...@@ -9,18 +9,13 @@ ...@@ -9,18 +9,13 @@
#include <sys/xattr.h> #include <sys/xattr.h>
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "components/download/quarantine/quarantine.h" #include "components/download/quarantine/common_linux.h"
#include "components/download/quarantine/quarantine_constants_linux.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace download { namespace download {
const char kSourceURLExtendedAttrName[] = "user.xdg.origin.url";
const char kReferrerURLExtendedAttrName[] = "user.xdg.referrer.url";
namespace { namespace {
bool SetExtendedFileAttribute(const char* path, bool SetExtendedFileAttribute(const char* path,
...@@ -38,27 +33,12 @@ bool SetExtendedFileAttribute(const char* path, ...@@ -38,27 +33,12 @@ bool SetExtendedFileAttribute(const char* path,
return true; return true;
} }
std::string GetExtendedFileAttribute(const char* path, const char* name) {
base::AssertBlockingAllowed();
ssize_t len = getxattr(path, name, nullptr, 0);
if (len <= 0)
return std::string();
std::vector<char> buffer(len);
len = getxattr(path, name, buffer.data(), buffer.size());
if (len < static_cast<ssize_t>(buffer.size()))
return std::string();
return std::string(buffer.begin(), buffer.end());
}
} // namespace } // namespace
QuarantineFileResult QuarantineFile(const base::FilePath& file, QuarantineFileResult QuarantineFile(const base::FilePath& file,
const GURL& source_url, const GURL& source_url,
const GURL& referrer_url, const GURL& referrer_url,
const std::string& client_guid) { const std::string& client_guid) {
DCHECK(base::PathIsWritable(file));
bool source_succeeded = bool source_succeeded =
source_url.is_valid() && source_url.is_valid() &&
SetExtendedFileAttribute(file.value().c_str(), kSourceURLExtendedAttrName, SetExtendedFileAttribute(file.value().c_str(), kSourceURLExtendedAttrName,
...@@ -77,24 +57,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, ...@@ -77,24 +57,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
: QuarantineFileResult::ANNOTATION_FAILED; : QuarantineFileResult::ANNOTATION_FAILED;
} }
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
if (!base::PathExists(file))
return false;
std::string url_value = GetExtendedFileAttribute(file.value().c_str(),
kSourceURLExtendedAttrName);
if (source_url.is_empty())
return !url_value.empty();
if (source_url != GURL(url_value))
return false;
return !referrer_url.is_valid() ||
GURL(GetExtendedFileAttribute(file.value().c_str(),
kReferrerURLExtendedAttrName)) ==
referrer_url;
}
} // namespace download } // namespace download
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "components/download/quarantine/quarantine.h"
#include <errno.h> #include <errno.h>
#include <stddef.h> #include <stddef.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -16,8 +18,8 @@ ...@@ -16,8 +18,8 @@
#include "base/files/scoped_temp_dir.h" #include "base/files/scoped_temp_dir.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "components/download/quarantine/quarantine.h" #include "components/download/quarantine/common_linux.h"
#include "components/download/quarantine/quarantine_constants_linux.h" #include "components/download/quarantine/test_support.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "components/download/quarantine/common_mac.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace { namespace {
...@@ -30,34 +31,6 @@ namespace { ...@@ -30,34 +31,6 @@ namespace {
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wdeprecated-declarations"
bool GetQuarantinePropertiesDeprecated(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties) {
const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
FSRef file_ref;
if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
return false;
base::ScopedCFTypeRef<CFTypeRef> quarantine_properties;
OSStatus status =
LSCopyItemAttribute(&file_ref, kLSRolesAll, kLSItemQuarantineProperties,
quarantine_properties.InitializeInto());
if (status != noErr)
return true;
CFDictionaryRef quarantine_properties_dict =
base::mac::CFCast<CFDictionaryRef>(quarantine_properties.get());
if (!quarantine_properties_dict) {
LOG(WARNING) << "kLSItemQuarantineProperties is not a dictionary on file "
<< file.value();
return false;
}
properties->reset(
[base::mac::CFToNSCast(quarantine_properties_dict) mutableCopy]);
return true;
}
bool SetQuarantinePropertiesDeprecated(const base::FilePath& file, bool SetQuarantinePropertiesDeprecated(const base::FilePath& file,
NSDictionary* properties) { NSDictionary* properties) {
const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str()); const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
...@@ -77,43 +50,6 @@ bool SetQuarantinePropertiesDeprecated(const base::FilePath& file, ...@@ -77,43 +50,6 @@ bool SetQuarantinePropertiesDeprecated(const base::FilePath& file,
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
API_AVAILABLE(macos(10.10))
bool GetQuarantineProperties(
const base::FilePath& file,
base::scoped_nsobject<NSMutableDictionary>* properties) {
base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
if (!file_url)
return false;
NSError* error = nil;
id quarantine_properties = nil;
BOOL success = [file_url getResourceValue:&quarantine_properties
forKey:NSURLQuarantinePropertiesKey
error:&error];
if (!success) {
std::string error_message(error ? error.description.UTF8String : "");
LOG(WARNING) << "Unable to get quarantine attributes for file "
<< file.value() << ". Error: " << error_message;
return false;
}
if (!quarantine_properties)
return true;
NSDictionary* quarantine_properties_dict =
base::mac::ObjCCast<NSDictionary>(quarantine_properties);
if (!quarantine_properties_dict) {
LOG(WARNING) << "Quarantine properties have wrong class: "
<< base::SysNSStringToUTF8(
[[quarantine_properties class] description]);
return false;
}
properties->reset([quarantine_properties_dict mutableCopy]);
return true;
}
API_AVAILABLE(macos(10.10)) API_AVAILABLE(macos(10.10))
bool SetQuarantineProperties(const base::FilePath& file, bool SetQuarantineProperties(const base::FilePath& file,
NSDictionary* properties) { NSDictionary* properties) {
...@@ -304,39 +240,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, ...@@ -304,39 +240,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
: QuarantineFileResult::ANNOTATION_FAILED; : QuarantineFileResult::ANNOTATION_FAILED;
} }
bool IsFileQuarantined(const base::FilePath& file,
const GURL& expected_source_url,
const GURL& referrer_url) {
base::AssertBlockingAllowed();
if (!base::PathExists(file))
return false;
base::scoped_nsobject<NSMutableDictionary> properties;
bool success = false;
if (@available(macos 10.10, *)) {
success = GetQuarantineProperties(file, &properties);
} else {
success = GetQuarantinePropertiesDeprecated(file, &properties);
}
if (!success || !properties)
return false;
NSString* source_url =
[[properties valueForKey:(NSString*)kLSQuarantineDataURLKey] description];
if (!expected_source_url.is_valid())
return [source_url length] > 0;
if (![source_url
isEqualToString:base::SysUTF8ToNSString(expected_source_url.spec())])
return false;
return !referrer_url.is_valid() ||
[[[properties valueForKey:(NSString*)kLSQuarantineOriginURLKey]
description]
isEqualToString:base::SysUTF8ToNSString(referrer_url.spec())];
}
} // namespace download } // namespace download
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "components/download/quarantine/quarantine.h"
#include <sys/xattr.h> #include <sys/xattr.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
...@@ -14,7 +16,7 @@ ...@@ -14,7 +16,7 @@
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "components/download/quarantine/quarantine.h" #include "components/download/quarantine/test_support.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h" #include "testing/gtest_mac.h"
#include "url/gurl.h" #include "url/gurl.h"
......
...@@ -23,54 +23,18 @@ ...@@ -23,54 +23,18 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/win/scoped_handle.h" #include "base/win/scoped_handle.h"
#include "base/win/win_util.h" #include "base/win/win_util.h"
#include "components/download/quarantine/common_win.h"
#include "components/download/quarantine/quarantine_features_win.h" #include "components/download/quarantine/quarantine_features_win.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace download { namespace download {
namespace { namespace {
// [MS-FSCC] Section 5.6.1
const base::FilePath::CharType kZoneIdentifierStreamSuffix[] =
FILE_PATH_LITERAL(":Zone.Identifier");
bool ZoneIdentifierPresentForFile(const base::FilePath& path) {
const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
base::FilePath::StringType zone_identifier_path =
path.value() + kZoneIdentifierStreamSuffix;
base::win::ScopedHandle file(
CreateFile(zone_identifier_path.c_str(), GENERIC_READ, kShare, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
if (!file.IsValid())
return false;
// The zone identifier contents is expected to be:
// "[ZoneTransfer]\r\nZoneId=3\r\n". The actual ZoneId can be different. A
// buffer of 32 bytes is sufficient for verifying the contents.
std::vector<char> zone_identifier_contents_buffer(32);
DWORD actual_length = 0;
if (!ReadFile(file.Get(), &zone_identifier_contents_buffer.front(),
zone_identifier_contents_buffer.size(), &actual_length,
nullptr))
return false;
zone_identifier_contents_buffer.resize(actual_length);
std::string zone_identifier_contents(zone_identifier_contents_buffer.begin(),
zone_identifier_contents_buffer.end());
std::vector<base::StringPiece> lines =
base::SplitStringPiece(zone_identifier_contents, "\n",
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
return lines.size() > 1 && lines[0] == "[ZoneTransfer]" &&
lines[1].find("ZoneId=") == 0;
}
// Returns true for a valid |url| whose length does not exceed // Returns true for a valid |url| whose length does not exceed
// INTERNET_MAX_URL_LENGTH. // INTERNET_MAX_URL_LENGTH.
bool IsValidUrlForAttachmentServices(const GURL& url) { bool IsValidUrlForAttachmentServices(const GURL& url) {
...@@ -93,9 +57,10 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly( ...@@ -93,9 +57,10 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly(
const GURL& referrer_url) { const GURL& referrer_url) {
const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
std::wstring path = full_path.value() + kZoneIdentifierStreamSuffix; std::wstring path = full_path.value() + kZoneIdentifierStreamSuffix;
HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, nullptr, base::win::ScopedHandle file(::CreateFile(path.c_str(), GENERIC_WRITE, kShare,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); nullptr, OPEN_ALWAYS,
if (INVALID_HANDLE_VALUE == file) FILE_ATTRIBUTE_NORMAL, nullptr));
if (!file.IsValid())
return QuarantineFileResult::ANNOTATION_FAILED; return QuarantineFileResult::ANNOTATION_FAILED;
static const char kReferrerUrlFormat[] = "ReferrerUrl=%s\r\n"; static const char kReferrerUrlFormat[] = "ReferrerUrl=%s\r\n";
...@@ -117,10 +82,9 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly( ...@@ -117,10 +82,9 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly(
// Don't include trailing null in data written. // Don't include trailing null in data written.
DWORD written = 0; DWORD written = 0;
BOOL write_result = WriteFile(file, identifier.c_str(), identifier.length(), BOOL write_result = ::WriteFile(file.Get(), identifier.c_str(),
&written, nullptr); identifier.length(), &written, nullptr);
BOOL flush_result = FlushFileBuffers(file); BOOL flush_result = FlushFileBuffers(file.Get());
CloseHandle(file);
return write_result && flush_result && written == identifier.length() return write_result && flush_result && written == identifier.length()
? QuarantineFileResult::OK ? QuarantineFileResult::OK
...@@ -309,10 +273,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, ...@@ -309,10 +273,4 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
return QuarantineFileResult::OK; return QuarantineFileResult::OK;
} }
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
return ZoneIdentifierPresentForFile(file);
}
} // namespace download } // namespace download
// Copyright 2018 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 "components/download/quarantine/test_support.h"
#include "build/build_config.h"
#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
namespace download {
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
return false;
}
} // namespace download
#endif // !WIN && !MAC && !LINUX
// Copyright 2018 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.
#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
#define COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
#include <string>
class GURL;
namespace base {
class FilePath;
}
namespace download {
// Determine if a file has quarantine metadata attached to it.
//
// If |source_url| is non-empty, then the download source URL in
// quarantine metadata should match |source_url| exactly. The function returns
// |false| if there is a mismatch. If |source_url| is empty, then this function
// only checks for the existence of a download source URL in quarantine
// metadata.
//
// If |referrer_url| is valid, then the download referrer URL in quarantine
// metadata must match |referrer_url| exactly. The function returns |false| if
// there is a mismatch in the |referrer_url| even if the |source_url| matches.
// No referrer URL checks are performed if |referrer_url| is empty.
//
// If both |source_url| and |referrer_url| are empty, then the function returns
// true if any quarantine metadata is present for the file.
//
// **Note**: On Windows 8 or lower, this function only checks if the
// |ZoneIdentifier| metadata is present. |source_url| and |referrer_url| are
// ignored. Individual URLs are only stored as part of the mark-of-the-web since
// Windows 10.
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url);
} // namespace download
#endif // COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
// Copyright 2018 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 "components/download/quarantine/test_support.h"
#include <stddef.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <string>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/threading/thread_restrictions.h"
#include "components/download/quarantine/common_linux.h"
#include "url/gurl.h"
namespace download {
namespace {
std::string GetExtendedFileAttribute(const char* path, const char* name) {
base::AssertBlockingAllowed();
ssize_t len = getxattr(path, name, nullptr, 0);
if (len <= 0)
return std::string();
std::vector<char> buffer(len);
len = getxattr(path, name, buffer.data(), buffer.size());
if (len < static_cast<ssize_t>(buffer.size()))
return std::string();
return std::string(buffer.begin(), buffer.end());
}
} // namespace
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
if (!base::PathExists(file))
return false;
std::string url_value = GetExtendedFileAttribute(file.value().c_str(),
kSourceURLExtendedAttrName);
if (source_url.is_empty())
return !url_value.empty();
if (source_url != GURL(url_value))
return false;
return !referrer_url.is_valid() ||
GURL(GetExtendedFileAttribute(file.value().c_str(),
kReferrerURLExtendedAttrName)) ==
referrer_url;
}
} // namespace download
// Copyright 2018 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 "components/download/quarantine/test_support.h"
#import <ApplicationServices/ApplicationServices.h>
#import <Foundation/Foundation.h>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "components/download/quarantine/common_mac.h"
#include "url/gurl.h"
namespace download {
bool IsFileQuarantined(const base::FilePath& file,
const GURL& expected_source_url,
const GURL& referrer_url) {
base::AssertBlockingAllowed();
if (!base::PathExists(file))
return false;
base::scoped_nsobject<NSMutableDictionary> properties;
bool success = false;
if (@available(macos 10.10, *))
success = GetQuarantineProperties(file, &properties);
else
success = GetQuarantinePropertiesDeprecated(file, &properties);
if (!success || !properties)
return false;
NSString* source_url =
[[properties valueForKey:(NSString*)kLSQuarantineDataURLKey] description];
if (!expected_source_url.is_valid())
return [source_url length] > 0;
if (![source_url isEqualToString:base::SysUTF8ToNSString(
expected_source_url.spec())]) {
return false;
}
return !referrer_url.is_valid() ||
[[[properties valueForKey:(NSString*)kLSQuarantineOriginURLKey]
description]
isEqualToString:base::SysUTF8ToNSString(referrer_url.spec())];
}
} // namespace download
// Copyright 2018 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 "components/download/quarantine/test_support.h"
#include <windows.h>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/win/scoped_handle.h"
#include "components/download/quarantine/common_win.h"
namespace download {
namespace {
bool ZoneIdentifierPresentForFile(const base::FilePath& path) {
const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
base::FilePath::StringType zone_identifier_path =
path.value() + kZoneIdentifierStreamSuffix;
base::win::ScopedHandle file(
::CreateFile(zone_identifier_path.c_str(), GENERIC_READ, kShare, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
if (!file.IsValid())
return false;
// The zone identifier contents is expected to be:
// "[ZoneTransfer]\r\nZoneId=3\r\n". The actual ZoneId can be different. A
// buffer of 32 bytes is sufficient for verifying the contents.
std::vector<char> zone_identifier_contents_buffer(32);
DWORD actual_length = 0;
if (!::ReadFile(file.Get(), &zone_identifier_contents_buffer.front(),
zone_identifier_contents_buffer.size(), &actual_length,
nullptr))
return false;
zone_identifier_contents_buffer.resize(actual_length);
std::string zone_identifier_contents(zone_identifier_contents_buffer.begin(),
zone_identifier_contents_buffer.end());
std::vector<base::StringPiece> lines =
base::SplitStringPiece(zone_identifier_contents, "\n",
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
return lines.size() > 1 && lines[0] == "[ZoneTransfer]" &&
lines[1].find("ZoneId=") == 0;
}
} // namespace
bool IsFileQuarantined(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url) {
return ZoneIdentifierPresentForFile(file);
}
} // namespace download
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment