// Copyright (c) 2012 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 "content/public/common/quarantine.h" #include #include #include #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/threading/thread_restrictions.h" #include "content/common/quarantine/quarantine_constants_linux.h" #include "url/gurl.h" namespace content { const char kSourceURLExtendedAttrName[] = "user.xdg.origin.url"; const char kReferrerURLExtendedAttrName[] = "user.xdg.referrer.url"; namespace { bool SetExtendedFileAttribute(const char* path, const char* name, const char* value, size_t value_size, int flags) { base::ThreadRestrictions::AssertIOAllowed(); int result = setxattr(path, name, value, value_size, flags); if (result) { DPLOG(ERROR) << "Could not set extended attribute " << name << " on file " << path; return false; } return true; } std::string GetExtendedFileAttribute(const char* path, const char* name) { base::ThreadRestrictions::AssertIOAllowed(); ssize_t len = getxattr(path, name, nullptr, 0); if (len <= 0) return std::string(); std::vector buffer(len); len = getxattr(path, name, buffer.data(), buffer.size()); if (len < static_cast(buffer.size())) return std::string(); return std::string(buffer.begin(), buffer.end()); } } // namespace QuarantineFileResult QuarantineFile(const base::FilePath& file, const GURL& source_url, const GURL& referrer_url, const std::string& client_guid) { DCHECK(base::PathIsWritable(file)); bool source_succeeded = source_url.is_valid() && SetExtendedFileAttribute(file.value().c_str(), kSourceURLExtendedAttrName, source_url.spec().c_str(), source_url.spec().length(), 0); // Referrer being empty is not considered an error. This could happen if the // referrer policy resulted in an empty referrer for the download request. bool referrer_succeeded = !referrer_url.is_valid() || SetExtendedFileAttribute( file.value().c_str(), kReferrerURLExtendedAttrName, referrer_url.spec().c_str(), referrer_url.spec().length(), 0); return source_succeeded && referrer_succeeded ? QuarantineFileResult::OK : 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 content