1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/net/chrome_network_delegate.h"
6
7 #include "base/base_paths.h"
8 #include "base/logging.h"
9 #include "base/path_service.h"
10 #include "build/build_config.h"
11
12 #if defined(OS_ANDROID)
13 #include "base/android/path_utils.h"
14 #endif
15
16 namespace {
17
18 bool g_access_to_all_files_enabled = false;
19
IsAccessAllowedInternal(const base::FilePath & path,const base::FilePath & profile_path)20 bool IsAccessAllowedInternal(const base::FilePath& path,
21 const base::FilePath& profile_path) {
22 if (g_access_to_all_files_enabled)
23 return true;
24
25 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
26 return true;
27 #else
28
29 std::vector<base::FilePath> whitelist;
30 #if defined(OS_CHROMEOS)
31 // Use a whitelist to only allow access to files residing in the list of
32 // directories below.
33 static const base::FilePath::CharType* const kLocalAccessWhiteList[] = {
34 "/home/chronos/user/Downloads",
35 "/home/chronos/user/MyFiles",
36 "/home/chronos/user/log",
37 "/home/chronos/user/WebRTC Logs",
38 "/media",
39 "/opt/oem",
40 "/run/arc/sdcard/write/emulated/0",
41 "/usr/share/chromeos-assets",
42 "/var/log",
43 };
44
45 base::FilePath temp_dir;
46 if (base::PathService::Get(base::DIR_TEMP, &temp_dir))
47 whitelist.push_back(temp_dir);
48
49 // The actual location of "/home/chronos/user/Xyz" is the Xyz directory under
50 // the profile path ("/home/chronos/user' is a hard link to current primary
51 // logged in profile.) For the support of multi-profile sessions, we are
52 // switching to use explicit "$PROFILE_PATH/Xyz" path and here whitelist such
53 // access.
54 if (!profile_path.empty()) {
55 const base::FilePath downloads = profile_path.AppendASCII("Downloads");
56 whitelist.push_back(downloads);
57 whitelist.push_back(profile_path.AppendASCII("MyFiles"));
58 const base::FilePath webrtc_logs = profile_path.AppendASCII("WebRTC Logs");
59 whitelist.push_back(webrtc_logs);
60 }
61 #elif defined(OS_ANDROID)
62 // Access to files in external storage is allowed.
63 base::FilePath external_storage_path;
64 base::PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE,
65 &external_storage_path);
66 if (external_storage_path.IsParent(path))
67 return true;
68
69 auto all_download_dirs = base::android::GetAllPrivateDownloadsDirectories();
70 for (const auto& dir : all_download_dirs)
71 whitelist.push_back(dir);
72
73 // Whitelist of other allowed directories.
74 static const base::FilePath::CharType* const kLocalAccessWhiteList[] = {
75 "/sdcard", "/mnt/sdcard",
76 };
77 #endif
78
79 for (const auto* whitelisted_path : kLocalAccessWhiteList)
80 whitelist.push_back(base::FilePath(whitelisted_path));
81
82 for (const auto& whitelisted_path : whitelist) {
83 // base::FilePath::operator== should probably handle trailing separators.
84 if (whitelisted_path == path.StripTrailingSeparators() ||
85 whitelisted_path.IsParent(path)) {
86 return true;
87 }
88 }
89
90 #if defined(OS_CHROMEOS)
91 // Allow access to DriveFS logs. These reside in
92 // $PROFILE_PATH/GCache/v2/<opaque id>/Logs.
93 base::FilePath path_within_gcache_v2;
94 if (profile_path.Append("GCache/v2")
95 .AppendRelativePath(path, &path_within_gcache_v2)) {
96 std::vector<std::string> components;
97 path_within_gcache_v2.GetComponents(&components);
98 if (components.size() > 1 && components[1] == "Logs") {
99 return true;
100 }
101 }
102 #endif // defined(OS_CHROMEOS)
103
104 DVLOG(1) << "File access denied - " << path.value().c_str();
105 return false;
106 #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
107 }
108
109 } // namespace
110
111 // static
IsAccessAllowed(const base::FilePath & path,const base::FilePath & profile_path)112 bool ChromeNetworkDelegate::IsAccessAllowed(
113 const base::FilePath& path,
114 const base::FilePath& profile_path) {
115 return IsAccessAllowedInternal(path, profile_path);
116 }
117
118 // static
IsAccessAllowed(const base::FilePath & path,const base::FilePath & absolute_path,const base::FilePath & profile_path)119 bool ChromeNetworkDelegate::IsAccessAllowed(
120 const base::FilePath& path,
121 const base::FilePath& absolute_path,
122 const base::FilePath& profile_path) {
123 #if defined(OS_ANDROID)
124 // Android's whitelist relies on symbolic links (ex. /sdcard is whitelisted
125 // and commonly a symbolic link), thus do not check absolute paths.
126 return IsAccessAllowedInternal(path, profile_path);
127 #else
128 return (IsAccessAllowedInternal(path, profile_path) &&
129 IsAccessAllowedInternal(absolute_path, profile_path));
130 #endif
131 }
132
133 // static
EnableAccessToAllFilesForTesting(bool enabled)134 void ChromeNetworkDelegate::EnableAccessToAllFilesForTesting(bool enabled) {
135 g_access_to_all_files_enabled = enabled;
136 }
137