OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/safe_browsing/download_protection_util.h" | 5 #include "chrome/common/safe_browsing/download_protection_util.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
8 #include "base/logging.h" | 10 #include "base/logging.h" |
9 | 11 |
10 namespace safe_browsing { | 12 namespace safe_browsing { |
11 namespace download_protection_util { | 13 namespace download_protection_util { |
12 | 14 |
| 15 namespace { |
| 16 |
| 17 // This enum matches the SBClientDownloadExtensions enum in histograms.xml. If |
| 18 // you are adding a value here, you should also add to the enum definition in |
| 19 // histograms.xml. Additions only at the end just in front of EXTENSION_MAX, |
| 20 // natch. |
| 21 enum SBClientDownloadExtensions { |
| 22 EXTENSION_EXE, |
| 23 EXTENSION_MSI, |
| 24 EXTENSION_CAB, |
| 25 EXTENSION_SYS, |
| 26 EXTENSION_SCR, |
| 27 EXTENSION_DRV, |
| 28 EXTENSION_BAT, |
| 29 EXTENSION_ZIP, |
| 30 EXTENSION_RAR, |
| 31 EXTENSION_DLL, |
| 32 EXTENSION_PIF, |
| 33 EXTENSION_COM, |
| 34 EXTENSION_JAR, |
| 35 EXTENSION_CLASS, |
| 36 EXTENSION_PDF, |
| 37 EXTENSION_VB, |
| 38 EXTENSION_REG, |
| 39 EXTENSION_GRP, |
| 40 EXTENSION_OTHER, // The "other" bucket. This is in the middle of the enum |
| 41 // due to historical reasons. |
| 42 EXTENSION_CRX, |
| 43 EXTENSION_APK, |
| 44 EXTENSION_DMG, |
| 45 EXTENSION_PKG, |
| 46 EXTENSION_TORRENT, |
| 47 EXTENSION_WEBSITE, |
| 48 EXTENSION_URL, |
| 49 EXTENSION_VBE, |
| 50 EXTENSION_VBS, |
| 51 EXTENSION_JS, |
| 52 EXTENSION_JSE, |
| 53 EXTENSION_MHT, |
| 54 EXTENSION_MHTML, |
| 55 EXTENSION_MSC, |
| 56 EXTENSION_MSP, |
| 57 EXTENSION_MST, |
| 58 EXTENSION_BAS, |
| 59 EXTENSION_HTA, |
| 60 EXTENSION_MSH, |
| 61 EXTENSION_MSH1, |
| 62 EXTENSION_MSH1XML, |
| 63 EXTENSION_MSH2, |
| 64 EXTENSION_MSH2XML, |
| 65 EXTENSION_MSHXML, |
| 66 EXTENSION_PS1, |
| 67 EXTENSION_PS1XML, |
| 68 EXTENSION_PS2, |
| 69 EXTENSION_PS2XML, |
| 70 EXTENSION_PSC1, |
| 71 EXTENSION_PSC2, |
| 72 EXTENSION_SCF, |
| 73 EXTENSION_SCT, |
| 74 EXTENSION_WSF, |
| 75 EXTENSION_7Z, |
| 76 EXTENSION_XZ, |
| 77 EXTENSION_GZ, |
| 78 EXTENSION_TGZ, |
| 79 EXTENSION_BZ2, |
| 80 EXTENSION_TAR, |
| 81 EXTENSION_ARJ, |
| 82 EXTENSION_LZH, |
| 83 EXTENSION_LHA, |
| 84 EXTENSION_WIM, |
| 85 EXTENSION_Z, |
| 86 EXTENSION_LZMA, |
| 87 EXTENSION_CPIO, |
| 88 EXTENSION_CMD, |
| 89 EXTENSION_APP, |
| 90 EXTENSION_OSX, |
| 91 |
| 92 // New values go above this one. |
| 93 EXTENSION_MAX |
| 94 }; |
| 95 |
| 96 struct SafeBrowsingFiletype { |
| 97 const base::FilePath::CharType* const extension; |
| 98 int uma_value; |
| 99 bool is_supported_binary; |
| 100 bool is_archive; |
| 101 }; |
| 102 |
| 103 const SafeBrowsingFiletype kSafeBrowsingFileTypes[] = { |
| 104 // KEEP THIS LIST SORTED! |
| 105 {FILE_PATH_LITERAL(".7z"), EXTENSION_7Z, false, true}, |
| 106 {FILE_PATH_LITERAL(".apk"), EXTENSION_APK, true, false}, |
| 107 {FILE_PATH_LITERAL(".app"), EXTENSION_APP, true, false}, |
| 108 {FILE_PATH_LITERAL(".arj"), EXTENSION_ARJ, false, true}, |
| 109 {FILE_PATH_LITERAL(".bas"), EXTENSION_BAS, true, false}, |
| 110 {FILE_PATH_LITERAL(".bat"), EXTENSION_BAT, true, false}, |
| 111 {FILE_PATH_LITERAL(".bz2"), EXTENSION_BZ2, false, true}, |
| 112 {FILE_PATH_LITERAL(".cab"), EXTENSION_CAB, false, true}, |
| 113 {FILE_PATH_LITERAL(".cmd"), EXTENSION_CMD, true, false}, |
| 114 {FILE_PATH_LITERAL(".com"), EXTENSION_COM, true, false}, |
| 115 {FILE_PATH_LITERAL(".cpio"), EXTENSION_CPIO, false, true}, |
| 116 {FILE_PATH_LITERAL(".crx"), EXTENSION_CRX, true, false}, |
| 117 {FILE_PATH_LITERAL(".dll"), EXTENSION_DLL, true, false}, |
| 118 {FILE_PATH_LITERAL(".dmg"), EXTENSION_DMG, true, false}, |
| 119 {FILE_PATH_LITERAL(".exe"), EXTENSION_EXE, true, false}, |
| 120 {FILE_PATH_LITERAL(".gz"), EXTENSION_GZ, false, true}, |
| 121 {FILE_PATH_LITERAL(".hta"), EXTENSION_HTA, true, false}, |
| 122 {FILE_PATH_LITERAL(".js"), EXTENSION_JS, true, false}, |
| 123 {FILE_PATH_LITERAL(".jse"), EXTENSION_JSE, true, false}, |
| 124 {FILE_PATH_LITERAL(".lha"), EXTENSION_LHA, false, true}, |
| 125 {FILE_PATH_LITERAL(".lzh"), EXTENSION_LZH, false, true}, |
| 126 {FILE_PATH_LITERAL(".lzma"), EXTENSION_LZMA, false, true}, |
| 127 {FILE_PATH_LITERAL(".mht"), EXTENSION_MHT, true, false}, |
| 128 {FILE_PATH_LITERAL(".mhtml"), EXTENSION_MHTML, true, false}, |
| 129 {FILE_PATH_LITERAL(".msc"), EXTENSION_MSC, true, false}, |
| 130 {FILE_PATH_LITERAL(".msh"), EXTENSION_MSH, true, false}, |
| 131 {FILE_PATH_LITERAL(".msh1"), EXTENSION_MSH1, true, false}, |
| 132 {FILE_PATH_LITERAL(".msh1xml"), EXTENSION_MSH1XML, true, false}, |
| 133 {FILE_PATH_LITERAL(".msh2"), EXTENSION_MSH2, true, false}, |
| 134 {FILE_PATH_LITERAL(".msh2xml"), EXTENSION_MSH2XML, true, false}, |
| 135 {FILE_PATH_LITERAL(".mshxml"), EXTENSION_MSHXML, true, false}, |
| 136 {FILE_PATH_LITERAL(".msi"), EXTENSION_MSI, true, false}, |
| 137 {FILE_PATH_LITERAL(".msp"), EXTENSION_MSP, true, false}, |
| 138 {FILE_PATH_LITERAL(".mst"), EXTENSION_MST, true, false}, |
| 139 {FILE_PATH_LITERAL(".osx"), EXTENSION_OSX, true, false}, |
| 140 {FILE_PATH_LITERAL(".pif"), EXTENSION_PIF, true, false}, |
| 141 {FILE_PATH_LITERAL(".pkg"), EXTENSION_PKG, true, false}, |
| 142 {FILE_PATH_LITERAL(".ps1"), EXTENSION_PS1, true, false}, |
| 143 {FILE_PATH_LITERAL(".ps1xml"), EXTENSION_PS1XML, true, false}, |
| 144 {FILE_PATH_LITERAL(".ps2"), EXTENSION_PS2, true, false}, |
| 145 {FILE_PATH_LITERAL(".ps2xml"), EXTENSION_PS2XML, true, false}, |
| 146 {FILE_PATH_LITERAL(".psc1"), EXTENSION_PSC1, true, false}, |
| 147 {FILE_PATH_LITERAL(".psc2"), EXTENSION_PSC2, true, false}, |
| 148 {FILE_PATH_LITERAL(".rar"), EXTENSION_RAR, false, true}, |
| 149 {FILE_PATH_LITERAL(".reg"), EXTENSION_REG, true, false}, |
| 150 {FILE_PATH_LITERAL(".scf"), EXTENSION_SCF, true, false}, |
| 151 {FILE_PATH_LITERAL(".scr"), EXTENSION_SCR, true, false}, |
| 152 {FILE_PATH_LITERAL(".sct"), EXTENSION_SCT, true, false}, |
| 153 {FILE_PATH_LITERAL(".tar"), EXTENSION_TAR, false, true}, |
| 154 {FILE_PATH_LITERAL(".tgz"), EXTENSION_TGZ, false, true}, |
| 155 {FILE_PATH_LITERAL(".url"), EXTENSION_URL, true, false}, |
| 156 {FILE_PATH_LITERAL(".vb"), EXTENSION_VB, true, false}, |
| 157 {FILE_PATH_LITERAL(".vbe"), EXTENSION_VBE, true, false}, |
| 158 {FILE_PATH_LITERAL(".vbs"), EXTENSION_VBS, true, false}, |
| 159 {FILE_PATH_LITERAL(".website"), EXTENSION_WEBSITE, true, false}, |
| 160 {FILE_PATH_LITERAL(".wim"), EXTENSION_WIM, false, true}, |
| 161 {FILE_PATH_LITERAL(".wsf"), EXTENSION_WSF, true, false}, |
| 162 {FILE_PATH_LITERAL(".xz"), EXTENSION_XZ, false, true}, |
| 163 {FILE_PATH_LITERAL(".z"), EXTENSION_Z, false, true}, |
| 164 {FILE_PATH_LITERAL(".zip"), EXTENSION_ZIP, true, true}, |
| 165 }; |
| 166 |
| 167 const SafeBrowsingFiletype& GetFileType(const base::FilePath& file) { |
| 168 static const SafeBrowsingFiletype kOther = { |
| 169 nullptr, EXTENSION_OTHER, false, false |
| 170 }; |
| 171 |
| 172 base::FilePath::StringType extension = file.FinalExtension(); |
| 173 SafeBrowsingFiletype needle = {extension.c_str()}; |
| 174 |
| 175 const auto begin = kSafeBrowsingFileTypes; |
| 176 const auto end = kSafeBrowsingFileTypes + arraysize(kSafeBrowsingFileTypes); |
| 177 const auto result = std::lower_bound( |
| 178 begin, end, needle, |
| 179 [](const SafeBrowsingFiletype& left, const SafeBrowsingFiletype& right) { |
| 180 return base::FilePath::CompareLessIgnoreCase(left.extension, |
| 181 right.extension); |
| 182 }); |
| 183 if (result == end || |
| 184 !base::FilePath::CompareEqualIgnoreCase(needle.extension, |
| 185 result->extension)) |
| 186 return kOther; |
| 187 return *result; |
| 188 } |
| 189 |
| 190 } // namespace |
| 191 |
| 192 const int kSBClientDownloadExtensionsMax = EXTENSION_MAX; |
| 193 |
13 bool IsArchiveFile(const base::FilePath& file) { | 194 bool IsArchiveFile(const base::FilePath& file) { |
14 // List of interesting archive file formats. These are by no means exhaustive, | 195 // List of interesting archive file formats in kSafeBrowsingFileTypes is by no |
15 // but are currently file types that Safe Browsing would like to see pings for | 196 // means exhaustive, but are currently file types that Safe Browsing would |
16 // due to the possibility of them being used as wrapper formats for malicious | 197 // like to see pings for due to the possibility of them being used as wrapper |
17 // payloads. | 198 // formats for malicious payloads. |
18 const base::FilePath::CharType* kArchiveFileTypes[] = { | 199 return GetFileType(file).is_archive; |
19 FILE_PATH_LITERAL(".zip"), | |
20 FILE_PATH_LITERAL(".rar"), | |
21 FILE_PATH_LITERAL(".7z"), | |
22 FILE_PATH_LITERAL(".cab"), | |
23 FILE_PATH_LITERAL(".xz"), | |
24 FILE_PATH_LITERAL(".gz"), | |
25 FILE_PATH_LITERAL(".tgz"), | |
26 FILE_PATH_LITERAL(".bz2"), | |
27 FILE_PATH_LITERAL(".tar"), | |
28 FILE_PATH_LITERAL(".arj"), | |
29 FILE_PATH_LITERAL(".lzh"), | |
30 FILE_PATH_LITERAL(".lha"), | |
31 FILE_PATH_LITERAL(".wim"), | |
32 FILE_PATH_LITERAL(".z"), | |
33 FILE_PATH_LITERAL(".lzma"), | |
34 FILE_PATH_LITERAL(".cpio"), | |
35 }; | |
36 for (const auto& extension : kArchiveFileTypes) { | |
37 if (file.MatchesExtension(extension)) | |
38 return true; | |
39 } | |
40 // TODO(mattm): should .dmg be checked here instead of IsSupportedBinaryFile? | |
41 return false; | |
42 } | 200 } |
43 | 201 |
44 bool IsSupportedBinaryFile(const base::FilePath& file) { | 202 bool IsSupportedBinaryFile(const base::FilePath& file) { |
45 const base::FilePath::CharType* kSupportedBinaryFileTypes[] = { | 203 return GetFileType(file).is_supported_binary; |
46 // Executable extensions for MS Windows. | |
47 FILE_PATH_LITERAL(".cmd"), | |
48 FILE_PATH_LITERAL(".com"), | |
49 FILE_PATH_LITERAL(".dll"), | |
50 FILE_PATH_LITERAL(".exe"), | |
51 FILE_PATH_LITERAL(".msc"), | |
52 FILE_PATH_LITERAL(".msi"), | |
53 FILE_PATH_LITERAL(".msp"), | |
54 FILE_PATH_LITERAL(".mst"), | |
55 FILE_PATH_LITERAL(".pif"), | |
56 FILE_PATH_LITERAL(".scr"), | |
57 // Not binary, but still contain executable code, or can be used to launch | |
58 // other executables. | |
59 FILE_PATH_LITERAL(".bas"), | |
60 FILE_PATH_LITERAL(".bat"), | |
61 FILE_PATH_LITERAL(".hta"), | |
62 FILE_PATH_LITERAL(".js"), | |
63 FILE_PATH_LITERAL(".jse"), | |
64 FILE_PATH_LITERAL(".mht"), | |
65 FILE_PATH_LITERAL(".mhtml"), | |
66 FILE_PATH_LITERAL(".msh"), | |
67 FILE_PATH_LITERAL(".msh1"), | |
68 FILE_PATH_LITERAL(".msh1xml"), | |
69 FILE_PATH_LITERAL(".msh2"), | |
70 FILE_PATH_LITERAL(".msh2xml"), | |
71 FILE_PATH_LITERAL(".mshxml"), | |
72 FILE_PATH_LITERAL(".ps1"), | |
73 FILE_PATH_LITERAL(".ps1xml"), | |
74 FILE_PATH_LITERAL(".ps2"), | |
75 FILE_PATH_LITERAL(".ps2xml"), | |
76 FILE_PATH_LITERAL(".psc1"), | |
77 FILE_PATH_LITERAL(".psc2"), | |
78 FILE_PATH_LITERAL(".reg"), | |
79 FILE_PATH_LITERAL(".scf"), | |
80 FILE_PATH_LITERAL(".sct"), | |
81 FILE_PATH_LITERAL(".url"), | |
82 FILE_PATH_LITERAL(".vb"), | |
83 FILE_PATH_LITERAL(".vbe"), | |
84 FILE_PATH_LITERAL(".vbs"), | |
85 FILE_PATH_LITERAL(".website"), | |
86 FILE_PATH_LITERAL(".wsf"), | |
87 // Chrome extensions and android APKs are also reported. | |
88 FILE_PATH_LITERAL(".apk"), | |
89 FILE_PATH_LITERAL(".crx"), | |
90 // Mac extensions. | |
91 FILE_PATH_LITERAL(".app"), | |
92 FILE_PATH_LITERAL(".dmg"), | |
93 FILE_PATH_LITERAL(".osx"), | |
94 FILE_PATH_LITERAL(".pkg"), | |
95 }; | |
96 for (const auto& extension : kSupportedBinaryFileTypes) | |
97 if (file.MatchesExtension(extension)) | |
98 return true; | |
99 | |
100 // .zip files are examined for any executables or other archives they may | |
101 // contain. Currently no other archive formats are supported. | |
102 return file.MatchesExtension(FILE_PATH_LITERAL(".zip")); | |
103 } | 204 } |
104 | 205 |
105 ClientDownloadRequest::DownloadType GetDownloadType( | 206 ClientDownloadRequest::DownloadType GetDownloadType( |
106 const base::FilePath& file) { | 207 const base::FilePath& file) { |
107 DCHECK(IsSupportedBinaryFile(file)); | 208 DCHECK(IsSupportedBinaryFile(file)); |
108 if (file.MatchesExtension(FILE_PATH_LITERAL(".apk"))) | 209 if (file.MatchesExtension(FILE_PATH_LITERAL(".apk"))) |
109 return ClientDownloadRequest::ANDROID_APK; | 210 return ClientDownloadRequest::ANDROID_APK; |
110 else if (file.MatchesExtension(FILE_PATH_LITERAL(".crx"))) | 211 else if (file.MatchesExtension(FILE_PATH_LITERAL(".crx"))) |
111 return ClientDownloadRequest::CHROME_EXTENSION; | 212 return ClientDownloadRequest::CHROME_EXTENSION; |
112 else if (file.MatchesExtension(FILE_PATH_LITERAL(".zip"))) | 213 else if (file.MatchesExtension(FILE_PATH_LITERAL(".zip"))) |
113 // DownloadProtectionService doesn't send a ClientDownloadRequest for ZIP | 214 // DownloadProtectionService doesn't send a ClientDownloadRequest for ZIP |
114 // files unless they contain either executables or archives. The resulting | 215 // files unless they contain either executables or archives. The resulting |
115 // DownloadType is either ZIPPED_EXECUTABLE or ZIPPED_ARCHIVE respectively. | 216 // DownloadType is either ZIPPED_EXECUTABLE or ZIPPED_ARCHIVE respectively. |
116 // This function will return ZIPPED_EXECUTABLE for ZIP files as a | 217 // This function will return ZIPPED_EXECUTABLE for ZIP files as a |
117 // placeholder. The correct DownloadType will be determined based on the | 218 // placeholder. The correct DownloadType will be determined based on the |
118 // result of analyzing the ZIP file. | 219 // result of analyzing the ZIP file. |
119 return ClientDownloadRequest::ZIPPED_EXECUTABLE; | 220 return ClientDownloadRequest::ZIPPED_EXECUTABLE; |
120 else if (file.MatchesExtension(FILE_PATH_LITERAL(".dmg")) || | 221 else if (file.MatchesExtension(FILE_PATH_LITERAL(".dmg")) || |
121 file.MatchesExtension(FILE_PATH_LITERAL(".pkg")) || | 222 file.MatchesExtension(FILE_PATH_LITERAL(".pkg")) || |
122 file.MatchesExtension(FILE_PATH_LITERAL(".osx")) || | 223 file.MatchesExtension(FILE_PATH_LITERAL(".osx")) || |
123 file.MatchesExtension(FILE_PATH_LITERAL(".app"))) | 224 file.MatchesExtension(FILE_PATH_LITERAL(".app"))) |
124 return ClientDownloadRequest::MAC_EXECUTABLE; | 225 return ClientDownloadRequest::MAC_EXECUTABLE; |
125 return ClientDownloadRequest::WIN_EXECUTABLE; | 226 return ClientDownloadRequest::WIN_EXECUTABLE; |
126 } | 227 } |
127 | 228 |
| 229 int GetSBClientDownloadExtensionValueForUMA(const base::FilePath& file) { |
| 230 return GetFileType(file).uma_value; |
| 231 } |
| 232 |
128 } // namespace download_protection_util | 233 } // namespace download_protection_util |
129 } // namespace safe_browsing | 234 } // namespace safe_browsing |
OLD | NEW |