1 // Copyright (c) 2006-2008 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 // Program to test the SafeBrowsing protocol parsing v2.1. 6 7 #include "base/string_util.h" 8 #include "chrome/browser/safe_browsing/protocol_parser.h" 9 #include "chrome/browser/safe_browsing/safe_browsing_util.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 // Test parsing one add chunk. 13 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) { 14 std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999"); 15 add_chunk[13] = '\0'; 16 17 // Run the parse. 18 SafeBrowsingProtocolParser parser; 19 bool re_key = false; 20 SBChunkList chunks; 21 bool result = parser.ParseChunk( 22 safe_browsing_util::kMalwareList, 23 add_chunk.data(), 24 static_cast<int>(add_chunk.length()), 25 "", "", &re_key, &chunks); 26 EXPECT_TRUE(result); 27 EXPECT_FALSE(re_key); 28 EXPECT_EQ(chunks.size(), 1U); 29 EXPECT_EQ(chunks[0].chunk_number, 1); 30 EXPECT_EQ(chunks[0].hosts.size(), 3U); 31 32 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 33 SBEntry* entry = chunks[0].hosts[0].entry; 34 EXPECT_TRUE(entry->IsAdd()); 35 EXPECT_TRUE(entry->IsPrefix()); 36 EXPECT_EQ(entry->prefix_count(), 0); 37 38 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 39 entry = chunks[0].hosts[1].entry; 40 EXPECT_TRUE(entry->IsAdd()); 41 EXPECT_TRUE(entry->IsPrefix()); 42 EXPECT_EQ(entry->prefix_count(), 3); 43 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 44 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 45 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 46 47 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 48 entry = chunks[0].hosts[2].entry; 49 EXPECT_TRUE(entry->IsAdd()); 50 EXPECT_TRUE(entry->IsPrefix()); 51 EXPECT_EQ(entry->prefix_count(), 2); 52 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 53 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 54 } 55 56 // Test parsing one add chunk with full hashes. 57 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) { 58 std::string add_chunk("a:1:32:69\naaaa"); 59 add_chunk.push_back(2); 60 61 SBFullHash full_hash1, full_hash2; 62 for (int i = 0; i < 32; ++i) { 63 full_hash1.full_hash[i] = i % 2 ? 1 : 2; 64 full_hash2.full_hash[i] = i % 2 ? 3 : 4; 65 } 66 67 add_chunk.append(full_hash1.full_hash, 32); 68 add_chunk.append(full_hash2.full_hash, 32); 69 70 // Run the parse. 71 SafeBrowsingProtocolParser parser; 72 bool re_key = false; 73 SBChunkList chunks; 74 bool result = parser.ParseChunk( 75 safe_browsing_util::kMalwareList, 76 add_chunk.data(), 77 static_cast<int>(add_chunk.length()), 78 "", "", &re_key, &chunks); 79 EXPECT_TRUE(result); 80 EXPECT_FALSE(re_key); 81 EXPECT_EQ(chunks.size(), 1U); 82 EXPECT_EQ(chunks[0].chunk_number, 1); 83 EXPECT_EQ(chunks[0].hosts.size(), 1U); 84 85 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 86 SBEntry* entry = chunks[0].hosts[0].entry; 87 EXPECT_TRUE(entry->IsAdd()); 88 EXPECT_FALSE(entry->IsPrefix()); 89 EXPECT_EQ(entry->prefix_count(), 2); 90 EXPECT_TRUE(entry->FullHashAt(0) == full_hash1); 91 EXPECT_TRUE(entry->FullHashAt(1) == full_hash2); 92 } 93 94 // Test parsing multiple add chunks. We'll use the same chunk as above, and add 95 // one more after it. 96 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) { 97 std::string add_chunk("a:1:4:35\naaaax1111\0032222333344447777\00288889999" 98 "a:2:4:13\n5555\002ppppgggg"); 99 add_chunk[13] = '\0'; 100 101 // Run the parse. 102 SafeBrowsingProtocolParser parser; 103 bool re_key = false; 104 SBChunkList chunks; 105 bool result = parser.ParseChunk( 106 safe_browsing_util::kMalwareList, 107 add_chunk.data(), 108 static_cast<int>(add_chunk.length()), 109 "", "", &re_key, &chunks); 110 EXPECT_TRUE(result); 111 EXPECT_FALSE(re_key); 112 EXPECT_EQ(chunks.size(), 2U); 113 EXPECT_EQ(chunks[0].chunk_number, 1); 114 EXPECT_EQ(chunks[0].hosts.size(), 3U); 115 116 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 117 SBEntry* entry = chunks[0].hosts[0].entry; 118 EXPECT_TRUE(entry->IsAdd()); 119 EXPECT_TRUE(entry->IsPrefix()); 120 EXPECT_EQ(entry->prefix_count(), 0); 121 122 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 123 entry = chunks[0].hosts[1].entry; 124 EXPECT_TRUE(entry->IsAdd()); 125 EXPECT_TRUE(entry->IsPrefix()); 126 EXPECT_EQ(entry->prefix_count(), 3); 127 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 128 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 129 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 130 131 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 132 entry = chunks[0].hosts[2].entry; 133 EXPECT_TRUE(entry->IsAdd()); 134 EXPECT_TRUE(entry->IsPrefix()); 135 EXPECT_EQ(entry->prefix_count(), 2); 136 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 137 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 138 139 140 EXPECT_EQ(chunks[1].chunk_number, 2); 141 EXPECT_EQ(chunks[1].hosts.size(), 1U); 142 143 EXPECT_EQ(chunks[1].hosts[0].host, 0x35353535); 144 entry = chunks[1].hosts[0].entry; 145 EXPECT_TRUE(entry->IsAdd()); 146 EXPECT_TRUE(entry->IsPrefix()); 147 EXPECT_EQ(entry->prefix_count(), 2); 148 EXPECT_EQ(entry->PrefixAt(0), 0x70707070); 149 EXPECT_EQ(entry->PrefixAt(1), 0x67676767); 150 } 151 152 // Test parsing one add chunk where a hostkey spans several entries. 153 TEST(SafeBrowsingProtocolParsingTest, TestAddBigChunk) { 154 std::string add_chunk("a:1:4:1050\naaaaX"); 155 add_chunk[add_chunk.size() - 1] |= 0xFF; 156 for (int i = 0; i < 255; ++i) 157 add_chunk.append(StringPrintf("%04d", i)); 158 159 add_chunk.append("aaaa"); 160 add_chunk.push_back(5); 161 for (int i = 0; i < 5; ++i) 162 add_chunk.append(StringPrintf("001%d", i)); 163 164 SafeBrowsingProtocolParser parser; 165 bool re_key = false; 166 SBChunkList chunks; 167 bool result = parser.ParseChunk( 168 safe_browsing_util::kMalwareList, 169 add_chunk.data(), 170 static_cast<int>(add_chunk.length()), 171 "", "", &re_key, &chunks); 172 EXPECT_TRUE(result); 173 EXPECT_FALSE(re_key); 174 EXPECT_EQ(chunks.size(), 1U); 175 EXPECT_EQ(chunks[0].chunk_number, 1); 176 177 EXPECT_EQ(chunks[0].hosts.size(), 2U); 178 179 const SBChunkHost& host0 = chunks[0].hosts[0]; 180 EXPECT_EQ(host0.host, 0x61616161); 181 EXPECT_EQ(host0.entry->prefix_count(), 255); 182 183 const SBChunkHost& host1 = chunks[0].hosts[1]; 184 EXPECT_EQ(host1.host, 0x61616161); 185 EXPECT_EQ(host1.entry->prefix_count(), 5); 186 } 187 188 // Test to make sure we could deal with truncated bin hash chunk. 189 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedBinHashChunk) { 190 // This chunk delares there are 4 prefixes but actually only contains 2. 191 const char add_chunk[] = "a:1:4:16\n11112222"; 192 SafeBrowsingProtocolParser parser; 193 bool re_key = false; 194 SBChunkList chunks; 195 bool result = parser.ParseChunk(add_chunk, 196 safe_browsing_util::kBinHashList, 197 static_cast<int>(sizeof(add_chunk)), 198 "", "", &re_key, &chunks); 199 EXPECT_FALSE(result); 200 EXPECT_FALSE(re_key); 201 EXPECT_EQ(chunks.size(), 0U); 202 } 203 204 // Test to make sure we could deal with truncated malwarelist chunk. 205 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedUrlHashChunk) { 206 // This chunk delares there are 4 prefixes but actually only contains 2. 207 const char add_chunk[] = "a:1:4:21\naaaa\00411112222"; 208 SafeBrowsingProtocolParser parser; 209 bool re_key = false; 210 SBChunkList chunks; 211 212 // For safe_browsing_util::kMalwareList. 213 bool result = parser.ParseChunk(add_chunk, 214 safe_browsing_util::kMalwareList, 215 static_cast<int>(sizeof(add_chunk)), 216 "", "", &re_key, &chunks); 217 EXPECT_FALSE(result); 218 EXPECT_FALSE(re_key); 219 EXPECT_EQ(chunks.size(), 0U); 220 221 // For safe_browsing_util::kPhishingList. 222 result = parser.ParseChunk(add_chunk, 223 safe_browsing_util::kPhishingList, 224 static_cast<int>(sizeof(add_chunk)), 225 "", "", &re_key, &chunks); 226 EXPECT_FALSE(result); 227 EXPECT_FALSE(re_key); 228 EXPECT_EQ(chunks.size(), 0U); 229 230 // For safe_browsing_util::kBinUrlList. 231 result = parser.ParseChunk(add_chunk, 232 safe_browsing_util::kBinUrlList, 233 static_cast<int>(sizeof(add_chunk)), 234 "", "", &re_key, &chunks); 235 EXPECT_FALSE(result); 236 EXPECT_FALSE(re_key); 237 EXPECT_EQ(chunks.size(), 0U); 238 } 239 240 // Test parsing one sub chunk. 241 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) { 242 std::string sub_chunk("s:9:4:59\naaaaxkkkk1111\003" 243 "zzzz2222zzzz3333zzzz4444" 244 "7777\002yyyy8888yyyy9999"); 245 sub_chunk[13] = '\0'; 246 247 // Run the parse. 248 SafeBrowsingProtocolParser parser; 249 bool re_key = false; 250 SBChunkList chunks; 251 bool result = parser.ParseChunk( 252 safe_browsing_util::kMalwareList, 253 sub_chunk.data(), 254 static_cast<int>(sub_chunk.length()), 255 "", "", &re_key, &chunks); 256 EXPECT_TRUE(result); 257 EXPECT_FALSE(re_key); 258 EXPECT_EQ(chunks.size(), 1U); 259 EXPECT_EQ(chunks[0].chunk_number, 9); 260 EXPECT_EQ(chunks[0].hosts.size(), 3U); 261 262 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 263 SBEntry* entry = chunks[0].hosts[0].entry; 264 EXPECT_TRUE(entry->IsSub()); 265 EXPECT_TRUE(entry->IsPrefix()); 266 EXPECT_EQ(entry->chunk_id(), 0x6b6b6b6b); 267 EXPECT_EQ(entry->prefix_count(), 0); 268 269 EXPECT_EQ(chunks[0].hosts[1].host, 0x31313131); 270 entry = chunks[0].hosts[1].entry; 271 EXPECT_TRUE(entry->IsSub()); 272 EXPECT_TRUE(entry->IsPrefix()); 273 EXPECT_EQ(entry->prefix_count(), 3); 274 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x7a7a7a7a); 275 EXPECT_EQ(entry->PrefixAt(0), 0x32323232); 276 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a); 277 EXPECT_EQ(entry->PrefixAt(1), 0x33333333); 278 EXPECT_EQ(entry->ChunkIdAtPrefix(2), 0x7a7a7a7a); 279 EXPECT_EQ(entry->PrefixAt(2), 0x34343434); 280 281 EXPECT_EQ(chunks[0].hosts[2].host, 0x37373737); 282 entry = chunks[0].hosts[2].entry; 283 EXPECT_TRUE(entry->IsSub()); 284 EXPECT_TRUE(entry->IsPrefix()); 285 EXPECT_EQ(entry->prefix_count(), 2); 286 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979); 287 EXPECT_EQ(entry->PrefixAt(0), 0x38383838); 288 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x79797979); 289 EXPECT_EQ(entry->PrefixAt(1), 0x39393939); 290 } 291 292 // Test parsing one sub chunk with full hashes. 293 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) { 294 std::string sub_chunk("s:1:32:77\naaaa"); 295 sub_chunk.push_back(2); 296 297 SBFullHash full_hash1, full_hash2; 298 for (int i = 0; i < 32; ++i) { 299 full_hash1.full_hash[i] = i % 2 ? 1 : 2; 300 full_hash2.full_hash[i] = i % 2 ? 3 : 4; 301 } 302 303 sub_chunk.append("yyyy"); 304 sub_chunk.append(full_hash1.full_hash, 32); 305 sub_chunk.append("zzzz"); 306 sub_chunk.append(full_hash2.full_hash, 32); 307 308 // Run the parse. 309 SafeBrowsingProtocolParser parser; 310 bool re_key = false; 311 SBChunkList chunks; 312 bool result = parser.ParseChunk( 313 safe_browsing_util::kMalwareList, 314 sub_chunk.data(), 315 static_cast<int>(sub_chunk.length()), 316 "", "", &re_key, &chunks); 317 EXPECT_TRUE(result); 318 EXPECT_FALSE(re_key); 319 EXPECT_EQ(chunks.size(), 1U); 320 EXPECT_EQ(chunks[0].chunk_number, 1); 321 EXPECT_EQ(chunks[0].hosts.size(), 1U); 322 323 EXPECT_EQ(chunks[0].hosts[0].host, 0x61616161); 324 SBEntry* entry = chunks[0].hosts[0].entry; 325 EXPECT_TRUE(entry->IsSub()); 326 EXPECT_FALSE(entry->IsPrefix()); 327 EXPECT_EQ(entry->prefix_count(), 2); 328 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x79797979); 329 EXPECT_TRUE(entry->FullHashAt(0) == full_hash1); 330 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x7a7a7a7a); 331 EXPECT_TRUE(entry->FullHashAt(1) == full_hash2); 332 } 333 334 // Test parsing the SafeBrowsing update response. 335 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) { 336 std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n" 337 "i:malware\nsd:21-27,42,171717\n"); 338 339 SafeBrowsingProtocolParser parser; 340 int next_query_sec = 0; 341 bool re_key = false; 342 bool reset = false; 343 std::vector<SBChunkDelete> deletes; 344 std::vector<ChunkUrl> urls; 345 EXPECT_TRUE(parser.ParseUpdate(add_del.data(), 346 static_cast<int>(add_del.length()), "", 347 &next_query_sec, &re_key, 348 &reset, &deletes, &urls)); 349 350 EXPECT_TRUE(urls.empty()); 351 EXPECT_FALSE(re_key); 352 EXPECT_FALSE(reset); 353 EXPECT_EQ(next_query_sec, 1700); 354 EXPECT_EQ(deletes.size(), 2U); 355 356 EXPECT_EQ(deletes[0].chunk_del.size(), 4U); 357 EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7)); 358 EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597)); 359 EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444)); 360 EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999)); 361 362 EXPECT_EQ(deletes[1].chunk_del.size(), 3U); 363 EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27)); 364 EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42)); 365 EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717)); 366 367 // An update response with missing list name. 368 369 next_query_sec = 0; 370 deletes.clear(); 371 urls.clear(); 372 add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n"; 373 EXPECT_FALSE(parser.ParseUpdate(add_del.data(), 374 static_cast<int>(add_del.length()), "", 375 &next_query_sec, &re_key, 376 &reset, &deletes, &urls)); 377 } 378 379 // Test parsing the SafeBrowsing update response. 380 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) { 381 std::string redirects("i:goog-malware-shavar\n" 382 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n" 383 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n" 384 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n" 385 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 386 "8691-8731,8733-8786\n"); 387 388 SafeBrowsingProtocolParser parser; 389 int next_query_sec = 0; 390 bool re_key = false; 391 bool reset = false; 392 std::vector<SBChunkDelete> deletes; 393 std::vector<ChunkUrl> urls; 394 EXPECT_TRUE(parser.ParseUpdate(redirects.data(), 395 static_cast<int>(redirects.length()), "", 396 &next_query_sec, &re_key, 397 &reset, &deletes, &urls)); 398 399 EXPECT_FALSE(re_key); 400 EXPECT_FALSE(reset); 401 EXPECT_EQ(urls.size(), 4U); 402 EXPECT_EQ(urls[0].url, 403 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1"); 404 EXPECT_EQ(urls[1].url, 405 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2"); 406 EXPECT_EQ(urls[2].url, 407 "cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3"); 408 EXPECT_EQ(urls[3].url, 409 "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 410 "8691-8731,8733-8786"); 411 EXPECT_EQ(next_query_sec, 0); 412 EXPECT_TRUE(deletes.empty()); 413 } 414 415 TEST(SafeBrowsingProtocolParsingTest, TestRedirectsWithMac) { 416 std::string redirects("i:goog-phish-shavar\n" 417 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6501-6505:6501-6505," 418 "pcY6iVeT9-CBQ3fdAF0rpnKjR1Y=\n" 419 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8001-8160:8001-8024," 420 "8026-8045,8048-8049,8051-8134,8136-8152,8155-8160," 421 "j6XXAEWnjYk9tVVLBSdQvIEq2Wg=\n"); 422 423 SafeBrowsingProtocolParser parser; 424 int next_query_sec = 0; 425 bool re_key = false; 426 bool reset = false; 427 const std::string key("58Lqn5WIP961x3zuLGo5Uw=="); 428 std::vector<SBChunkDelete> deletes; 429 std::vector<ChunkUrl> urls; 430 EXPECT_TRUE(parser.ParseUpdate(redirects.data(), 431 static_cast<int>(redirects.length()), key, 432 &next_query_sec, &re_key, 433 &reset, &deletes, &urls)); 434 435 EXPECT_FALSE(re_key); 436 EXPECT_FALSE(reset); 437 EXPECT_EQ(urls.size(), 2U); 438 EXPECT_EQ(urls[0].url, 439 "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6501-6505:6501-6505"); 440 EXPECT_EQ(urls[0].mac, "pcY6iVeT9-CBQ3fdAF0rpnKjR1Y="); 441 EXPECT_EQ(urls[1].url, 442 "s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8001-8160:8001-8024," 443 "8026-8045,8048-8049,8051-8134,8136-8152,8155-8160"); 444 EXPECT_EQ(urls[1].mac, "j6XXAEWnjYk9tVVLBSdQvIEq2Wg="); 445 } 446 447 // Test parsing various SafeBrowsing protocol headers. 448 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) { 449 std::string headers("n:1800\ni:goog-white-shavar\n"); 450 SafeBrowsingProtocolParser parser; 451 int next_query_sec = 0; 452 bool re_key = false; 453 bool reset = false; 454 std::vector<SBChunkDelete> deletes; 455 std::vector<ChunkUrl> urls; 456 EXPECT_TRUE(parser.ParseUpdate(headers.data(), 457 static_cast<int>(headers.length()), "", 458 &next_query_sec, &re_key, 459 &reset, &deletes, &urls)); 460 461 EXPECT_EQ(next_query_sec, 1800); 462 EXPECT_FALSE(re_key); 463 EXPECT_FALSE(reset); 464 EXPECT_TRUE(deletes.empty()); 465 EXPECT_TRUE(urls.empty()); 466 } 467 468 // Test parsing data from a GetHashRequest 469 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) { 470 std::string get_hash("goog-phish-shavar:19:96\n" 471 "00112233445566778899aabbccddeeff" 472 "00001111222233334444555566667777" 473 "ffffeeeeddddccccbbbbaaaa99998888"); 474 std::vector<SBFullHashResult> full_hashes; 475 bool re_key = false; 476 SafeBrowsingProtocolParser parser; 477 EXPECT_TRUE(parser.ParseGetHash(get_hash.data(), 478 static_cast<int>(get_hash.length()), "", 479 &re_key, 480 &full_hashes)); 481 482 EXPECT_FALSE(re_key); 483 EXPECT_EQ(full_hashes.size(), 3U); 484 EXPECT_EQ(memcmp(&full_hashes[0].hash, 485 "00112233445566778899aabbccddeeff", 486 sizeof(SBFullHash)), 0); 487 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 488 EXPECT_EQ(memcmp(&full_hashes[1].hash, 489 "00001111222233334444555566667777", 490 sizeof(SBFullHash)), 0); 491 EXPECT_EQ(full_hashes[1].list_name, "goog-phish-shavar"); 492 EXPECT_EQ(memcmp(&full_hashes[2].hash, 493 "ffffeeeeddddccccbbbbaaaa99998888", 494 sizeof(SBFullHash)), 0); 495 EXPECT_EQ(full_hashes[2].list_name, "goog-phish-shavar"); 496 497 // Test multiple lists in the GetHash results. 498 std::string get_hash2("goog-phish-shavar:19:32\n" 499 "00112233445566778899aabbccddeeff" 500 "goog-malware-shavar:19:64\n" 501 "cafebeefcafebeefdeaddeaddeaddead" 502 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss"); 503 EXPECT_TRUE(parser.ParseGetHash(get_hash2.data(), 504 static_cast<int>(get_hash2.length()), "", 505 &re_key, 506 &full_hashes)); 507 508 EXPECT_FALSE(re_key); 509 EXPECT_EQ(full_hashes.size(), 3U); 510 EXPECT_EQ(memcmp(&full_hashes[0].hash, 511 "00112233445566778899aabbccddeeff", 512 sizeof(SBFullHash)), 0); 513 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 514 EXPECT_EQ(memcmp(&full_hashes[1].hash, 515 "cafebeefcafebeefdeaddeaddeaddead", 516 sizeof(SBFullHash)), 0); 517 EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar"); 518 EXPECT_EQ(memcmp(&full_hashes[2].hash, 519 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", 520 sizeof(SBFullHash)), 0); 521 EXPECT_EQ(full_hashes[2].list_name, "goog-malware-shavar"); 522 } 523 524 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithMac) { 525 const unsigned char get_hash[] = { 526 0x32, 0x56, 0x74, 0x6f, 0x6b, 0x36, 0x64, 0x41, 527 0x51, 0x72, 0x65, 0x51, 0x62, 0x38, 0x51, 0x68, 528 0x59, 0x45, 0x57, 0x51, 0x57, 0x4d, 0x52, 0x65, 529 0x42, 0x63, 0x41, 0x3d, 0x0a, 0x67, 0x6f, 0x6f, 530 0x67, 0x2d, 0x70, 0x68, 0x69, 0x73, 0x68, 0x2d, 531 0x73, 0x68, 0x61, 0x76, 0x61, 0x72, 0x3a, 0x36, 532 0x31, 0x36, 0x39, 0x3a, 0x33, 0x32, 0x0a, 0x17, 533 0x7f, 0x03, 0x42, 0x28, 0x1c, 0x31, 0xb9, 0x0b, 534 0x1c, 0x7b, 0x9d, 0xaf, 0x7b, 0x43, 0x99, 0x10, 535 0xc1, 0xab, 0xe3, 0x1b, 0x35, 0x80, 0x38, 0x96, 536 0xf9, 0x44, 0x4f, 0x28, 0xb4, 0xeb, 0x45 537 }; 538 539 const unsigned char hash_result[] = { 540 0x17, 0x7f, 0x03, 0x42, 0x28, 0x1c, 0x31, 0xb9, 541 0x0b, 0x1c, 0x7b, 0x9d, 0xaf, 0x7b, 0x43, 0x99, 542 0x10, 0xc1, 0xab, 0xe3, 0x1b, 0x35, 0x80, 0x38, 543 0x96, 0xf9, 0x44, 0x4f, 0x28, 0xb4, 0xeb, 0x45 544 }; 545 546 const std::string key = "58Lqn5WIP961x3zuLGo5Uw=="; 547 std::vector<SBFullHashResult> full_hashes; 548 bool re_key = false; 549 SafeBrowsingProtocolParser parser; 550 EXPECT_TRUE(parser.ParseGetHash(reinterpret_cast<const char*>(get_hash), 551 sizeof(get_hash), 552 key, 553 &re_key, 554 &full_hashes)); 555 EXPECT_FALSE(re_key); 556 EXPECT_EQ(full_hashes.size(), 1U); 557 EXPECT_EQ(memcmp(hash_result, &full_hashes[0].hash, sizeof(SBFullHash)), 0); 558 } 559 560 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) { 561 std::string hash_response = "goog-phish-shavar:1:32\n" 562 "12345678901234567890123456789012" 563 "googpub-phish-shavar:19:32\n" 564 "09876543210987654321098765432109"; 565 bool re_key = false; 566 std::string key = ""; 567 std::vector<SBFullHashResult> full_hashes; 568 SafeBrowsingProtocolParser parser; 569 EXPECT_TRUE(parser.ParseGetHash(hash_response.data(), 570 hash_response.size(), 571 key, 572 &re_key, 573 &full_hashes)); 574 575 EXPECT_EQ(full_hashes.size(), 1U); 576 EXPECT_EQ(memcmp("12345678901234567890123456789012", 577 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 578 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 579 EXPECT_EQ(full_hashes[0].add_chunk_id, 1); 580 581 hash_response += "goog-malware-shavar:7:32\n" 582 "abcdefghijklmnopqrstuvwxyz123457"; 583 full_hashes.clear(); 584 EXPECT_TRUE(parser.ParseGetHash(hash_response.data(), 585 hash_response.size(), 586 key, 587 &re_key, 588 &full_hashes)); 589 590 EXPECT_EQ(full_hashes.size(), 2U); 591 EXPECT_EQ(memcmp("12345678901234567890123456789012", 592 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 593 EXPECT_EQ(full_hashes[0].list_name, "goog-phish-shavar"); 594 EXPECT_EQ(full_hashes[0].add_chunk_id, 1); 595 EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457", 596 &full_hashes[1].hash, sizeof(SBFullHash)), 0); 597 EXPECT_EQ(full_hashes[1].list_name, "goog-malware-shavar"); 598 EXPECT_EQ(full_hashes[1].add_chunk_id, 7); 599 } 600 601 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) { 602 SafeBrowsingProtocolParser parser; 603 std::vector<SBPrefix> prefixes; 604 std::string get_hash; 605 606 prefixes.push_back(0x34333231); 607 prefixes.push_back(0x64636261); 608 prefixes.push_back(0x73727170); 609 610 parser.FormatGetHash(prefixes, &get_hash); 611 EXPECT_EQ(get_hash, "4:12\n1234abcdpqrs"); 612 } 613 614 TEST(SafeBrowsingProtocolParsingTest, TestGetKey) { 615 SafeBrowsingProtocolParser parser; 616 std::string key_response("clientkey:10:0123456789\n" 617 "wrappedkey:20:abcdefghijklmnopqrst\n"); 618 619 std::string client_key, wrapped_key; 620 EXPECT_TRUE(parser.ParseNewKey(key_response.data(), 621 static_cast<int>(key_response.length()), 622 &client_key, 623 &wrapped_key)); 624 625 EXPECT_EQ(client_key, "0123456789"); 626 EXPECT_EQ(wrapped_key, "abcdefghijklmnopqrst"); 627 } 628 629 TEST(SafeBrowsingProtocolParsingTest, TestReKey) { 630 SafeBrowsingProtocolParser parser; 631 std::string update("n:1800\ni:phishy\ne:pleaserekey\n"); 632 633 bool re_key = false; 634 bool reset = false; 635 int next_update = -1; 636 std::vector<SBChunkDelete> deletes; 637 std::vector<ChunkUrl> urls; 638 EXPECT_TRUE(parser.ParseUpdate(update.data(), 639 static_cast<int>(update.size()), "", 640 &next_update, &re_key, 641 &reset, &deletes, &urls)); 642 EXPECT_TRUE(re_key); 643 } 644 645 TEST(SafeBrowsingProtocolParsingTest, TestReset) { 646 SafeBrowsingProtocolParser parser; 647 std::string update("n:1800\ni:phishy\nr:pleasereset\n"); 648 649 bool re_key = false; 650 bool reset = false; 651 int next_update = -1; 652 std::vector<SBChunkDelete> deletes; 653 std::vector<ChunkUrl> urls; 654 EXPECT_TRUE(parser.ParseUpdate(update.data(), 655 static_cast<int>(update.size()), "", 656 &next_update, &re_key, 657 &reset, &deletes, &urls)); 658 EXPECT_TRUE(reset); 659 } 660 661 // The SafeBrowsing service will occasionally send zero length chunks so that 662 // client requests will have longer contiguous chunk number ranges, and thus 663 // reduce the request size. 664 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) { 665 std::string add_chunk("a:1:4:0\n"); 666 SafeBrowsingProtocolParser parser; 667 bool re_key = false; 668 SBChunkList chunks; 669 670 bool result = parser.ParseChunk( 671 safe_browsing_util::kMalwareList, 672 add_chunk.data(), 673 static_cast<int>(add_chunk.length()), 674 "", "", &re_key, &chunks); 675 EXPECT_TRUE(result); 676 EXPECT_EQ(chunks.size(), 1U); 677 EXPECT_EQ(chunks[0].chunk_number, 1); 678 EXPECT_EQ(chunks[0].hosts.size(), 0U); 679 680 // Now test a zero size chunk in between normal chunks. 681 chunks.clear(); 682 std::string add_chunks("a:1:4:18\n1234\001abcd5678\001wxyz" 683 "a:2:4:0\n" 684 "a:3:4:9\ncafe\001beef"); 685 result = parser.ParseChunk( 686 safe_browsing_util::kMalwareList, 687 add_chunks.data(), 688 static_cast<int>(add_chunks.length()), 689 "", "", &re_key, &chunks); 690 EXPECT_TRUE(result); 691 EXPECT_EQ(chunks.size(), 3U); 692 693 // See that each chunk has the right content. 694 EXPECT_EQ(chunks[0].chunk_number, 1); 695 EXPECT_EQ(chunks[0].hosts.size(), 2U); 696 EXPECT_EQ(chunks[0].hosts[0].host, 0x34333231); 697 EXPECT_EQ(chunks[0].hosts[0].entry->PrefixAt(0), 0x64636261); 698 EXPECT_EQ(chunks[0].hosts[1].host, 0x38373635); 699 EXPECT_EQ(chunks[0].hosts[1].entry->PrefixAt(0), 0x7a797877); 700 701 EXPECT_EQ(chunks[1].chunk_number, 2); 702 EXPECT_EQ(chunks[1].hosts.size(), 0U); 703 704 EXPECT_EQ(chunks[2].chunk_number, 3); 705 EXPECT_EQ(chunks[2].hosts.size(), 1U); 706 EXPECT_EQ(chunks[2].hosts[0].host, 0x65666163); 707 EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x66656562); 708 } 709 710 // Test parsing a zero sized sub chunk. 711 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) { 712 std::string sub_chunk("s:9:4:0\n"); 713 SafeBrowsingProtocolParser parser; 714 bool re_key = false; 715 SBChunkList chunks; 716 717 bool result = parser.ParseChunk( 718 safe_browsing_util::kMalwareList, 719 sub_chunk.data(), 720 static_cast<int>(sub_chunk.length()), 721 "", "", &re_key, &chunks); 722 EXPECT_TRUE(result); 723 EXPECT_EQ(chunks.size(), 1U); 724 EXPECT_EQ(chunks[0].chunk_number, 9); 725 EXPECT_EQ(chunks[0].hosts.size(), 0U); 726 chunks.clear(); 727 728 // Test parsing a zero sized sub chunk mixed in with content carrying chunks. 729 std::string sub_chunks("s:1:4:9\nabcdxwxyz" 730 "s:2:4:0\n" 731 "s:3:4:26\nefgh\0011234pqrscafe\0015678lmno"); 732 sub_chunks[12] = '\0'; 733 734 result = parser.ParseChunk( 735 safe_browsing_util::kMalwareList, 736 sub_chunks.data(), 737 static_cast<int>(sub_chunks.length()), 738 "", "", &re_key, &chunks); 739 EXPECT_TRUE(result); 740 741 EXPECT_EQ(chunks[0].chunk_number, 1); 742 EXPECT_EQ(chunks[0].hosts.size(), 1U); 743 EXPECT_EQ(chunks[0].hosts[0].host, 0x64636261); 744 EXPECT_EQ(chunks[0].hosts[0].entry->prefix_count(), 0); 745 746 EXPECT_EQ(chunks[1].chunk_number, 2); 747 EXPECT_EQ(chunks[1].hosts.size(), 0U); 748 749 EXPECT_EQ(chunks[2].chunk_number, 3); 750 EXPECT_EQ(chunks[2].hosts.size(), 2U); 751 EXPECT_EQ(chunks[2].hosts[0].host, 0x68676665); 752 EXPECT_EQ(chunks[2].hosts[0].entry->prefix_count(), 1); 753 EXPECT_EQ(chunks[2].hosts[0].entry->PrefixAt(0), 0x73727170); 754 EXPECT_EQ(chunks[2].hosts[0].entry->ChunkIdAtPrefix(0), 0x31323334); 755 EXPECT_EQ(chunks[2].hosts[1].host, 0x65666163); 756 EXPECT_EQ(chunks[2].hosts[1].entry->prefix_count(), 1); 757 EXPECT_EQ(chunks[2].hosts[1].entry->PrefixAt(0), 0x6f6e6d6c); 758 EXPECT_EQ(chunks[2].hosts[1].entry->ChunkIdAtPrefix(0), 0x35363738); 759 } 760 761 TEST(SafeBrowsingProtocolParsingTest, TestVerifyUpdateMac) { 762 SafeBrowsingProtocolParser parser; 763 764 const std::string update = 765 "m:XIU0LiQhAPJq6dynXwHbygjS5tw=\n" 766 "n:1895\n" 767 "i:goog-phish-shavar\n" 768 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6501-6505:6501-6505," 769 "pcY6iVeT9-CBQ3fdAF0rpnKjR1Y=\n" 770 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6506-6510:6506-6510," 771 "SDBrYC3rX3KEPe72LOypnP6QYac=\n" 772 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6511-6520:6511-6520," 773 "9UQo-e7OkcsXT2wFWTAhOuWOsUs=\n" 774 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6521-6560:6521-6560," 775 "qVNw6JIpR1q6PIXST7J4LJ9n3Zg=\n" 776 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6561-6720:6561-6720," 777 "7OiJvCbiwvpzPITW-hQohY5NHuc=\n" 778 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6721-6880:6721-6880," 779 "oBS3svhoi9deIa0sWZ_gnD0ujj8=\n" 780 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_6881-7040:6881-7040," 781 "a0r8Xit4VvH39xgyQHZTPczKBIE=\n" 782 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_s_7041-7200:7041-7163," 783 "q538LChutGknBw55s6kcE2wTcvU=\n" 784 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8001-8160:8001-8024," 785 "8026-8045,8048-8049,8051-8134,8136-8152,8155-8160," 786 "j6XXAEWnjYk9tVVLBSdQvIEq2Wg=\n" 787 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8161-8320:8161-8215," 788 "8217-8222,8224-8320,YaNfiqdQOt-uLCLWVLj46AZpAjQ=\n" 789 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8321-8480:8321-8391," 790 "8393-8399,8402,8404-8419,8421-8425,8427,8431-8433,8435-8439,8441-8443," 791 "8445-8446,8448-8480,ALj31GQMwGiIeU3bM2ZYKITfU-U=\n" 792 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8481-8640:8481-8500," 793 "8502-8508,8510-8511,8513-8517,8519-8525,8527-8531,8533,8536-8539," 794 "8541-8576,8578-8638,8640,TlQYRmS_kZ5PBAUIUyNQDq0Jprs=\n" 795 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 796 "8691-8731,8733-8786,x1Qf7hdNrO8b6yym03ZzNydDS1o=\n"; 797 798 bool re_key = false; 799 bool reset = false; 800 int next_update = -1; 801 std::vector<SBChunkDelete> deletes; 802 std::vector<ChunkUrl> urls; 803 const std::string key("58Lqn5WIP961x3zuLGo5Uw=="); 804 EXPECT_TRUE(parser.ParseUpdate(update.data(), 805 static_cast<int>(update.size()), key, 806 &next_update, &re_key, 807 &reset, &deletes, &urls)); 808 EXPECT_FALSE(re_key); 809 EXPECT_EQ(next_update, 1895); 810 } 811 812 TEST(SafeBrowsingProtocolParsingTest, TestVerifyChunkMac) { 813 SafeBrowsingProtocolParser parser; 814 815 const unsigned char chunk[] = { 816 0x73, 0x3a, 0x32, 0x30, 0x30, 0x32, 0x3a, 0x34, 817 0x3a, 0x32, 0x32, 0x0a, 0x2f, 0x4f, 0x89, 0x7a, 818 0x01, 0x00, 0x00, 0x0a, 0x59, 0xc8, 0x71, 0xdf, 819 0x9d, 0x29, 0x0c, 0xba, 0xd7, 0x00, 0x00, 0x00, 820 0x0a, 0x59 821 }; 822 823 bool re_key = false; 824 SBChunkList chunks; 825 const std::string key("v_aDSz6jI92WeHCOoZ07QA=="); 826 const std::string mac("W9Xp2fUcQ9V66If6Cvsrstpa4Kk="); 827 828 EXPECT_TRUE(parser.ParseChunk( 829 safe_browsing_util::kMalwareList, 830 reinterpret_cast<const char*>(chunk), 831 sizeof(chunk), key, mac, 832 &re_key, &chunks)); 833 EXPECT_FALSE(re_key); 834 } 835 836 TEST(SafeBrowsingProtocolParsingTest, TestAddBinHashChunks) { 837 std::string add_chunk("a:1:4:16\naaaabbbbccccdddd" 838 "a:2:4:8\n11112222"); 839 // Run the parse. 840 SafeBrowsingProtocolParser parser; 841 bool re_key = false; 842 SBChunkList chunks; 843 bool result = parser.ParseChunk( 844 safe_browsing_util::kBinHashList, 845 add_chunk.data(), 846 static_cast<int>(add_chunk.length()), 847 "", "", &re_key, &chunks); 848 EXPECT_TRUE(result); 849 EXPECT_FALSE(re_key); 850 EXPECT_EQ(chunks.size(), 2U); 851 EXPECT_EQ(chunks[0].chunk_number, 1); 852 EXPECT_EQ(chunks[0].hosts.size(), 1U); 853 854 EXPECT_EQ(chunks[0].hosts[0].host, 0); 855 SBEntry* entry = chunks[0].hosts[0].entry; 856 EXPECT_TRUE(entry->IsAdd()); 857 EXPECT_TRUE(entry->IsPrefix()); 858 EXPECT_EQ(entry->prefix_count(), 4); 859 860 EXPECT_EQ(chunks[1].chunk_number, 2); 861 EXPECT_EQ(chunks[1].hosts.size(), 1U); 862 863 EXPECT_EQ(chunks[1].hosts[0].host, 0); 864 entry = chunks[1].hosts[0].entry; 865 EXPECT_TRUE(entry->IsAdd()); 866 EXPECT_TRUE(entry->IsPrefix()); 867 EXPECT_EQ(entry->prefix_count(), 2); 868 EXPECT_EQ(entry->PrefixAt(0), 0x31313131); 869 EXPECT_EQ(entry->PrefixAt(1), 0x32323232); 870 } 871 872 // Test parsing one add chunk where a hostkey spans several entries. 873 TEST(SafeBrowsingProtocolParsingTest, TestAddBigBinHashChunk) { 874 std::string add_chunk("a:1:4:1028\n"); 875 for (int i = 0; i < 257; ++i) 876 add_chunk.append(StringPrintf("%04d", i)); 877 878 SafeBrowsingProtocolParser parser; 879 bool re_key = false; 880 SBChunkList chunks; 881 bool result = parser.ParseChunk( 882 safe_browsing_util::kBinHashList, 883 add_chunk.data(), 884 static_cast<int>(add_chunk.length()), 885 "", "", &re_key, &chunks); 886 EXPECT_TRUE(result); 887 EXPECT_FALSE(re_key); 888 EXPECT_EQ(chunks.size(), 1U); 889 EXPECT_EQ(chunks[0].chunk_number, 1); 890 891 EXPECT_EQ(chunks[0].hosts.size(), 1U); 892 893 const SBChunkHost& host0 = chunks[0].hosts[0]; 894 EXPECT_EQ(host0.host, 0); 895 EXPECT_EQ(host0.entry->prefix_count(), 257); 896 } 897 898 // Test parsing one sub chunk. 899 TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) { 900 std::string sub_chunk("s:9:4:16\n1111mmmm2222nnnn"); 901 902 // Run the parser. 903 SafeBrowsingProtocolParser parser; 904 bool re_key = false; 905 SBChunkList chunks; 906 bool result = parser.ParseChunk( 907 safe_browsing_util::kBinHashList, 908 sub_chunk.data(), 909 static_cast<int>(sub_chunk.length()), 910 "", "", &re_key, &chunks); 911 EXPECT_TRUE(result); 912 EXPECT_FALSE(re_key); 913 EXPECT_EQ(chunks.size(), 1U); 914 EXPECT_EQ(chunks[0].chunk_number, 9); 915 EXPECT_EQ(chunks[0].hosts.size(), 1U); 916 917 EXPECT_EQ(chunks[0].hosts[0].host, 0); 918 SBEntry* entry = chunks[0].hosts[0].entry; 919 EXPECT_TRUE(entry->IsSub()); 920 EXPECT_TRUE(entry->IsPrefix()); 921 EXPECT_EQ(entry->prefix_count(), 2); 922 EXPECT_EQ(entry->ChunkIdAtPrefix(0), 0x31313131); 923 EXPECT_EQ(entry->PrefixAt(0), 0x6d6d6d6d); 924 EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232); 925 EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e); 926 } 927