1// Copyright (c) 2011 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 6#include "base/logging.h" 7#include "base/time.h" 8#include "testing/gtest/include/gtest/gtest.h" 9#include "chrome/browser/safe_browsing/protocol_manager.h" 10 11using base::Time; 12using base::TimeDelta; 13 14static const char kInfoUrlPrefix[] = "http://info.prefix.com/foo"; 15static const char kMacKeyUrlPrefix[] = "https://key.prefix.com/bar"; 16static const char kClient[] = "unittest"; 17static const char kAppVer[] = "1.0"; 18static const char kClientKey[] = "SCg9lcLHd0dfksXgYsacwQ=="; 19static const char kWrappedKey[] = 20 "AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqA" 21 "BiJZnDFByc_g8B5vTwxkhBf9g=="; 22static const char kAdditionalQuery[] = "additional_query"; 23 24class SafeBrowsingProtocolManagerTest : public testing::Test { 25}; 26 27// Ensure that we respect section 5 of the SafeBrowsing protocol specification. 28TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) { 29 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 30 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 31 pm.next_update_sec_ = 1800; 32 DCHECK(pm.back_off_fuzz_ >= 0.0 && pm.back_off_fuzz_ <= 1.0); 33 34 // No errors received so far. 35 EXPECT_EQ(pm.GetNextUpdateTime(false), 1800 * 1000); 36 37 // 1 error. 38 EXPECT_EQ(pm.GetNextUpdateTime(true), 60 * 1000); 39 40 // 2 errors. 41 int next_time = pm.GetNextUpdateTime(true) / (60 * 1000); // Minutes 42 EXPECT_TRUE(next_time >= 30 && next_time <= 60); 43 44 // 3 errors. 45 next_time = pm.GetNextUpdateTime(true) / (60 * 1000); 46 EXPECT_TRUE(next_time >= 60 && next_time <= 120); 47 48 // 4 errors. 49 next_time = pm.GetNextUpdateTime(true) / (60 * 1000); 50 EXPECT_TRUE(next_time >= 120 && next_time <= 240); 51 52 // 5 errors. 53 next_time = pm.GetNextUpdateTime(true) / (60 * 1000); 54 EXPECT_TRUE(next_time >= 240 && next_time <= 480); 55 56 // 6 errors, reached max backoff. 57 EXPECT_EQ(pm.GetNextUpdateTime(true), 480 * 60 * 1000); 58 59 // 7 errors. 60 EXPECT_EQ(pm.GetNextUpdateTime(true), 480 * 60 * 1000); 61 62 // Received a successful response. 63 EXPECT_EQ(pm.GetNextUpdateTime(false), 1800 * 1000); 64} 65 66// Test string combinations with and without MAC. 67TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) { 68 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 69 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 70 71 // Add and Sub chunks. 72 SBListChunkRanges phish("goog-phish-shavar"); 73 phish.adds = "1,4,6,8-20,99"; 74 phish.subs = "16,32,64-96"; 75 EXPECT_EQ(pm.FormatList(phish, false), 76 "goog-phish-shavar;a:1,4,6,8-20,99:s:16,32,64-96\n"); 77 EXPECT_EQ(pm.FormatList(phish, true), 78 "goog-phish-shavar;a:1,4,6,8-20,99:s:16,32,64-96:mac\n"); 79 80 // Add chunks only. 81 phish.subs = ""; 82 EXPECT_EQ(pm.FormatList(phish, false), 83 "goog-phish-shavar;a:1,4,6,8-20,99\n"); 84 EXPECT_EQ(pm.FormatList(phish, true), 85 "goog-phish-shavar;a:1,4,6,8-20,99:mac\n"); 86 87 // Sub chunks only. 88 phish.adds = ""; 89 phish.subs = "16,32,64-96"; 90 EXPECT_EQ(pm.FormatList(phish, false), "goog-phish-shavar;s:16,32,64-96\n"); 91 EXPECT_EQ(pm.FormatList(phish, true), 92 "goog-phish-shavar;s:16,32,64-96:mac\n"); 93 94 // No chunks of either type. 95 phish.adds = ""; 96 phish.subs = ""; 97 EXPECT_EQ(pm.FormatList(phish, false), "goog-phish-shavar;\n"); 98 EXPECT_EQ(pm.FormatList(phish, true), "goog-phish-shavar;mac\n"); 99} 100 101TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) { 102 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 103 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 104 105 // No errors or back off time yet. 106 EXPECT_EQ(pm.gethash_error_count_, 0); 107 EXPECT_TRUE(pm.next_gethash_time_.is_null()); 108 109 Time now = Time::Now(); 110 111 // 1 error. 112 pm.HandleGetHashError(now); 113 EXPECT_EQ(pm.gethash_error_count_, 1); 114 TimeDelta margin = TimeDelta::FromSeconds(5); // Fudge factor. 115 Time future = now + TimeDelta::FromMinutes(1); 116 EXPECT_TRUE(pm.next_gethash_time_ >= future - margin && 117 pm.next_gethash_time_ <= future + margin); 118 119 // 2 errors. 120 pm.HandleGetHashError(now); 121 EXPECT_EQ(pm.gethash_error_count_, 2); 122 EXPECT_TRUE(pm.next_gethash_time_ >= now + TimeDelta::FromMinutes(30)); 123 EXPECT_TRUE(pm.next_gethash_time_ <= now + TimeDelta::FromMinutes(60)); 124 125 // 3 errors. 126 pm.HandleGetHashError(now); 127 EXPECT_EQ(pm.gethash_error_count_, 3); 128 EXPECT_TRUE(pm.next_gethash_time_ >= now + TimeDelta::FromMinutes(60)); 129 EXPECT_TRUE(pm.next_gethash_time_ <= now + TimeDelta::FromMinutes(120)); 130 131 // 4 errors. 132 pm.HandleGetHashError(now); 133 EXPECT_EQ(pm.gethash_error_count_, 4); 134 EXPECT_TRUE(pm.next_gethash_time_ >= now + TimeDelta::FromMinutes(120)); 135 EXPECT_TRUE(pm.next_gethash_time_ <= now + TimeDelta::FromMinutes(240)); 136 137 // 5 errors. 138 pm.HandleGetHashError(now); 139 EXPECT_EQ(pm.gethash_error_count_, 5); 140 EXPECT_TRUE(pm.next_gethash_time_ >= now + TimeDelta::FromMinutes(240)); 141 EXPECT_TRUE(pm.next_gethash_time_ <= now + TimeDelta::FromMinutes(480)); 142 143 // 6 errors, reached max backoff. 144 pm.HandleGetHashError(now); 145 EXPECT_EQ(pm.gethash_error_count_, 6); 146 EXPECT_TRUE(pm.next_gethash_time_ == now + TimeDelta::FromMinutes(480)); 147 148 // 7 errors. 149 pm.HandleGetHashError(now); 150 EXPECT_EQ(pm.gethash_error_count_, 7); 151 EXPECT_TRUE(pm.next_gethash_time_== now + TimeDelta::FromMinutes(480)); 152} 153 154TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) { 155 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 156 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 157 pm.version_ = kAppVer; 158 EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" 159 "pver=2.2", pm.GetHashUrl(false).spec()); 160 EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" 161 "pver=2.2&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cE" 162 "ErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf9g==", 163 pm.GetHashUrl(true).spec()); 164 165 pm.set_additional_query(kAdditionalQuery); 166 EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" 167 "pver=2.2&additional_query", 168 pm.GetHashUrl(false).spec()); 169 EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" 170 "pver=2.2&additional_query&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8" 171 "nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf" 172 "9g==", pm.GetHashUrl(true).spec()); 173} 174 175TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) { 176 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 177 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 178 pm.version_ = kAppVer; 179 180 EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" 181 "pver=2.2", pm.UpdateUrl(false).spec()); 182 EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" 183 "pver=2.2&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cE" 184 "ErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf9g==", 185 pm.UpdateUrl(true).spec()); 186 187 pm.set_additional_query(kAdditionalQuery); 188 EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" 189 "pver=2.2&additional_query", pm.UpdateUrl(false).spec()); 190 EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" 191 "pver=2.2&additional_query&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8" 192 "nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf" 193 "9g==", pm.UpdateUrl(true).spec()); 194} 195 196TEST_F(SafeBrowsingProtocolManagerTest, TestSafeBrowsingHitUrl) { 197 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 198 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 199 pm.version_ = kAppVer; 200 201 GURL malicious_url("http://malicious.url.com"); 202 GURL page_url("http://page.url.com"); 203 GURL referrer_url("http://referrer.url.com"); 204 EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" 205 "pver=2.2&evts=malblhit&evtd=http%3A%2F%2Fmalicious.url.com%2F&" 206 "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." 207 "url.com%2F&evtb=1", 208 pm.SafeBrowsingHitUrl( 209 malicious_url, page_url, referrer_url, 210 true, SafeBrowsingService::URL_MALWARE).spec()); 211 212 pm.set_additional_query(kAdditionalQuery); 213 EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" 214 "pver=2.2&additional_query&evts=phishblhit&" 215 "evtd=http%3A%2F%2Fmalicious.url.com%2F&" 216 "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." 217 "url.com%2F&evtb=0", 218 pm.SafeBrowsingHitUrl( 219 malicious_url, page_url, referrer_url, 220 false, SafeBrowsingService::URL_PHISHING).spec()); 221 222 EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" 223 "pver=2.2&additional_query&evts=binurlhit&" 224 "evtd=http%3A%2F%2Fmalicious.url.com%2F&" 225 "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." 226 "url.com%2F&evtb=0", 227 pm.SafeBrowsingHitUrl( 228 malicious_url, page_url, referrer_url, 229 false, SafeBrowsingService::BINARY_MALWARE_URL).spec()); 230 231 EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" 232 "pver=2.2&additional_query&evts=binhashhit&" 233 "evtd=http%3A%2F%2Fmalicious.url.com%2F&" 234 "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." 235 "url.com%2F&evtb=0", 236 pm.SafeBrowsingHitUrl( 237 malicious_url, page_url, referrer_url, 238 false, SafeBrowsingService::BINARY_MALWARE_HASH).spec()); 239} 240 241TEST_F(SafeBrowsingProtocolManagerTest, TestMalwareDetailsUrl) { 242 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 243 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 244 245 pm.version_ = kAppVer; 246 pm.set_additional_query(kAdditionalQuery); // AdditionalQuery is not used. 247 EXPECT_EQ("https://key.prefix.com/bar/clientreport/malware?" 248 "client=unittest&appver=1.0&pver=1.0", 249 pm.MalwareDetailsUrl().spec()); 250} 251 252TEST_F(SafeBrowsingProtocolManagerTest, TestMacKeyUrl) { 253 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 254 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 255 pm.version_ = kAppVer; 256 257 EXPECT_EQ("https://key.prefix.com/bar/newkey?client=unittest&appver=1.0&" 258 "pver=2.2", pm.MacKeyUrl().spec()); 259 260 pm.set_additional_query(kAdditionalQuery); 261 EXPECT_EQ("https://key.prefix.com/bar/newkey?client=unittest&appver=1.0&" 262 "pver=2.2&additional_query", pm.MacKeyUrl().spec()); 263} 264 265TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) { 266 SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, 267 kInfoUrlPrefix, kMacKeyUrlPrefix, false); 268 pm.version_ = kAppVer; 269 270 std::string url_partial = "localhost:1234/foo/bar?foo"; 271 std::string url_http_full = "http://localhost:1234/foo/bar?foo"; 272 std::string url_https_full = "https://localhost:1234/foo/bar?foo"; 273 std::string url_https_no_query = "https://localhost:1234/foo/bar"; 274 275 EXPECT_EQ("http://localhost:1234/foo/bar?foo", 276 pm.NextChunkUrl(url_partial).spec()); 277 EXPECT_EQ("http://localhost:1234/foo/bar?foo", 278 pm.NextChunkUrl(url_http_full).spec()); 279 EXPECT_EQ("https://localhost:1234/foo/bar?foo", 280 pm.NextChunkUrl(url_https_full).spec()); 281 EXPECT_EQ("https://localhost:1234/foo/bar", 282 pm.NextChunkUrl(url_https_no_query).spec()); 283 284 pm.set_additional_query(kAdditionalQuery); 285 EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query", 286 pm.NextChunkUrl(url_partial).spec()); 287 EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query", 288 pm.NextChunkUrl(url_http_full).spec()); 289 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query", 290 pm.NextChunkUrl(url_https_full).spec()); 291 EXPECT_EQ("https://localhost:1234/foo/bar?additional_query", 292 pm.NextChunkUrl(url_https_no_query).spec()); 293} 294