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 <string> 6 7 #include "base/strings/stringprintf.h" 8 #include "base/time/time.h" 9 #include "chrome/browser/safe_browsing/protocol_parser.h" 10 #include "chrome/browser/safe_browsing/safe_browsing_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 namespace { 14 15 #if defined(OS_ANDROID) 16 const char kDefaultPhishList[] = "goog-mobilephish-shavar"; 17 const char kDefaultMalwareList[] = "goog-mobilemalware-shavar"; 18 #else 19 const char kDefaultPhishList[] = "goog-phish-shavar"; 20 const char kDefaultMalwareList[] = "goog-malware-shavar"; 21 #endif 22 23 // Test parsing one add chunk. 24 TEST(SafeBrowsingProtocolParsingTest, TestAddChunk) { 25 const char kRawAddChunk[] = { 26 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order. 27 '\x08', // field 1, wire format varint 28 '\x01', // chunk_number varint 1 29 '\x22', // field 4, wire format length-delimited 30 '\x18', // varint length 24 31 '1', '1', '1', '1', // 4-byte prefixes 32 '2', '2', '2', '2', 33 '3', '3', '3', '3', 34 '4', '4', '4', '4', 35 '8', '8', '8', '8', 36 '9', '9', '9', '9', 37 }; 38 39 ScopedVector<SBChunkData> chunks; 40 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 41 &chunks)); 42 ASSERT_EQ(1U, chunks.size()); 43 EXPECT_EQ(1, chunks[0]->ChunkNumber()); 44 EXPECT_TRUE(chunks[0]->IsAdd()); 45 EXPECT_FALSE(chunks[0]->IsSub()); 46 EXPECT_TRUE(chunks[0]->IsPrefix()); 47 EXPECT_FALSE(chunks[0]->IsFullHash()); 48 ASSERT_EQ(6U, chunks[0]->PrefixCount()); 49 EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0)); // 1111 50 EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1)); // 2222 51 EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2)); // 3333 52 EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3)); // 4444 53 EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4)); // 8888 54 EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5)); // 9999 55 } 56 57 // Test parsing one add chunk with full hashes. 58 TEST(SafeBrowsingProtocolParsingTest, TestAddFullChunk) { 59 const char kRawAddChunk[] = { 60 '\0', '\0', '\0', '\x46', // 32-bit payload length in network byte order. 61 '\x08', // field 1, wire format varint 62 '\x01', // chunk_number varint 1 63 '\x18', // field 3, wire format varint 64 '\x01', // enum PrefixType == FULL_32B 65 '\x22', // field 4, wire format length-delimited 66 '\x40', // varint length 64 (2 full hashes) 67 68 '0', '1', '0', '1', '0', '1', '0', '1', 69 '0', '1', '0', '1', '0', '1', '0', '1', 70 '0', '1', '0', '1', '0', '1', '0', '1', 71 '0', '1', '0', '1', '0', '1', '0', '1', 72 73 '2', '3', '2', '3', '2', '3', '2', '3', 74 '2', '3', '2', '3', '2', '3', '2', '3', 75 '2', '3', '2', '3', '2', '3', '2', '3', 76 '2', '3', '2', '3', '2', '3', '2', '3', 77 }; 78 79 SBFullHash full_hash1, full_hash2; 80 for (int i = 0; i < 32; ++i) { 81 full_hash1.full_hash[i] = i % 2 ? '1' : '0'; 82 full_hash2.full_hash[i] = i % 2 ? '3' : '2'; 83 } 84 85 ScopedVector<SBChunkData> chunks; 86 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 87 &chunks)); 88 ASSERT_EQ(1U, chunks.size()); 89 EXPECT_EQ(1, chunks[0]->ChunkNumber()); 90 EXPECT_TRUE(chunks[0]->IsAdd()); 91 EXPECT_FALSE(chunks[0]->IsSub()); 92 EXPECT_FALSE(chunks[0]->IsPrefix()); 93 EXPECT_TRUE(chunks[0]->IsFullHash()); 94 95 ASSERT_EQ(2U, chunks[0]->FullHashCount()); 96 EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); 97 EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); 98 } 99 100 // Test parsing multiple add chunks. We'll use the same chunk as above, and add 101 // one more after it. 102 TEST(SafeBrowsingProtocolParsingTest, TestAddChunks) { 103 const char kRawAddChunk[] = { 104 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order. 105 '\x08', // field 1, wire format varint 106 '\x01', // chunk_number varint 1 107 '\x22', // field 4, wire format length-delimited 108 '\x18', // varint length 24 109 110 '1', '1', '1', '1', // 4-byte prefixes 111 '2', '2', '2', '2', 112 '3', '3', '3', '3', 113 '4', '4', '4', '4', 114 '8', '8', '8', '8', 115 '9', '9', '9', '9', 116 117 '\0', '\0', '\0', '\x0C', // 32-bit payload length in network byte order. 118 '\x08', // field 1, wire format varint 119 '\x02', // chunk_number varint 1 120 '\x22', // field 4, wire format length-delimited 121 '\x08', // varint length 8 122 'p', 'p', 'p', 'p', // 4-byte prefixes 123 'g', 'g', 'g', 'g', 124 }; 125 126 ScopedVector<SBChunkData> chunks; 127 EXPECT_TRUE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 128 &chunks)); 129 ASSERT_EQ(2U, chunks.size()); 130 131 EXPECT_EQ(1, chunks[0]->ChunkNumber()); 132 EXPECT_TRUE(chunks[0]->IsAdd()); 133 EXPECT_FALSE(chunks[0]->IsSub()); 134 EXPECT_TRUE(chunks[0]->IsPrefix()); 135 EXPECT_FALSE(chunks[0]->IsFullHash()); 136 ASSERT_EQ(6U, chunks[0]->PrefixCount()); 137 EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0)); // 1111 138 EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1)); // 2222 139 EXPECT_EQ(0x33333333U, chunks[0]->PrefixAt(2)); // 3333 140 EXPECT_EQ(0x34343434U, chunks[0]->PrefixAt(3)); // 4444 141 EXPECT_EQ(0x38383838U, chunks[0]->PrefixAt(4)); // 8888 142 EXPECT_EQ(0x39393939U, chunks[0]->PrefixAt(5)); // 9999 143 144 EXPECT_EQ(2, chunks[1]->ChunkNumber()); 145 EXPECT_TRUE(chunks[1]->IsAdd()); 146 EXPECT_FALSE(chunks[1]->IsSub()); 147 EXPECT_TRUE(chunks[1]->IsPrefix()); 148 EXPECT_FALSE(chunks[1]->IsFullHash()); 149 ASSERT_EQ(2U, chunks[1]->PrefixCount()); 150 EXPECT_EQ(0x70707070U, chunks[1]->PrefixAt(0)); // pppp 151 EXPECT_EQ(0x67676767U, chunks[1]->PrefixAt(1)); // gggg 152 } 153 154 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedPrefixChunk) { 155 // This chunk delares there are 6 prefixes but actually only contains 3. 156 const char kRawAddChunk[] = { 157 '\0', '\0', '\0', '\x1C', // 32-bit payload length in network byte order. 158 '\x08', // field 1, wire format varint 159 '\x01', // chunk_number varint 1 160 '\x22', // field 4, wire format length-delimited 161 '\x18', // varint length 24 162 '1', '1', '1', '1', // 4-byte prefixes 163 '2', '2', '2', '2', 164 '3', '3', '3', '3', 165 }; 166 167 ScopedVector<SBChunkData> chunks; 168 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 169 &chunks)); 170 } 171 172 TEST(SafeBrowsingProtocolParsingTest, TestTruncatedFullHashChunk) { 173 // This chunk delares there are two full hashes but there is only one. 174 const char kRawAddChunk[] = { 175 '\0', '\0', '\0', '\x46', // 32-bit payload length in network byte order. 176 '\x08', // field 1, wire format varint 177 '\x01', // chunk_number varint 1 178 '\x18', // field 3, wire format varint 179 '\x01', // enum PrefixType == FULL_32B 180 '\x22', // field 4, wire format length-delimited 181 '\x40', // varint length 64 (2 full hashes) 182 183 '0', '1', '0', '1', '0', '1', '0', '1', 184 '0', '1', '0', '1', '0', '1', '0', '1', 185 '0', '1', '0', '1', '0', '1', '0', '1', 186 '0', '1', '0', '1', '0', '1', '0', '1', 187 }; 188 189 ScopedVector<SBChunkData> chunks; 190 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 191 &chunks)); 192 } 193 194 TEST(SafeBrowsingProtocolParsingTest, TestHugeChunk) { 195 // This chunk delares there are 6 prefixes but actually only contains 3. 196 const char kRawAddChunk[] = { 197 '\x1', '\0', '\0', '\0', // 32-bit payload length in network byte order. 198 '\x08', // field 1, wire format varint 199 '\x01', // chunk_number varint 1 200 '\x22', // field 4, wire format length-delimited 201 '\x18', // varint length 24 202 '1', '1', '1', '1', // 4-byte prefixes 203 '2', '2', '2', '2', 204 '3', '3', '3', '3', 205 }; 206 207 ScopedVector<SBChunkData> chunks; 208 EXPECT_FALSE(safe_browsing::ParseChunk(kRawAddChunk, sizeof(kRawAddChunk), 209 &chunks)); 210 } 211 212 // Test parsing one sub chunk. 213 TEST(SafeBrowsingProtocolParsingTest, TestSubChunk) { 214 const char kRawSubChunk[] = { 215 '\0', '\0', '\0', '\x12', // 32-bit payload length in network byte order 216 '\x08', // field 1, wire format varint 217 '\x03', // chunk_number varint 3 218 '\x10', // field 2, wire format varint 219 '\x01', // enum ChunkType == SUB 220 '\x22', // field 4, wire format length-delimited 221 '\x08', // varint length 8 (2 prefixes) 222 '1', '1', '1', '1', // 4-byte prefixes 223 '2', '2', '2', '2', 224 '\x2a', // field 5, wire format length-delimited 225 '\x02', // varint length 2 (2 add-chunk numbers) 226 '\x07', '\x09', // varint 7, varint 9 227 }; 228 229 ScopedVector<SBChunkData> chunks; 230 EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk), 231 &chunks)); 232 ASSERT_EQ(1U, chunks.size()); 233 EXPECT_EQ(3, chunks[0]->ChunkNumber()); 234 EXPECT_FALSE(chunks[0]->IsAdd()); 235 EXPECT_TRUE(chunks[0]->IsSub()); 236 EXPECT_TRUE(chunks[0]->IsPrefix()); 237 EXPECT_FALSE(chunks[0]->IsFullHash()); 238 ASSERT_EQ(2U, chunks[0]->PrefixCount()); 239 EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0)); // 1111 240 EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0)); 241 EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1)); // 2222 242 EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1)); 243 } 244 245 // Test parsing one sub chunk with full hashes. 246 TEST(SafeBrowsingProtocolParsingTest, TestSubFullChunk) { 247 const char kRawSubChunk[] = { 248 '\0', '\0', '\0', '\x4C', // 32-bit payload length in network byte order. 249 '\x08', // field 1, wire format varint 250 '\x02', // chunk_number varint 2 251 '\x10', // field 2, wire format varint 252 '\x01', // enum ChunkType == SUB 253 '\x18', // field 3, wire format varint 254 '\x01', // enum PrefixType == FULL_32B 255 '\x22', // field 4, wire format length-delimited 256 '\x40', // varint length 64 (2 full hashes) 257 258 '0', '1', '0', '1', '0', '1', '0', '1', 259 '0', '1', '0', '1', '0', '1', '0', '1', 260 '0', '1', '0', '1', '0', '1', '0', '1', 261 '0', '1', '0', '1', '0', '1', '0', '1', 262 263 '2', '3', '2', '3', '2', '3', '2', '3', 264 '2', '3', '2', '3', '2', '3', '2', '3', 265 '2', '3', '2', '3', '2', '3', '2', '3', 266 '2', '3', '2', '3', '2', '3', '2', '3', 267 268 '\x2a', // field 5, wire format length-delimited 269 '\x02', // varint length 2 (2 add-chunk numbers) 270 '\x07', '\x09', // varint 7, varint 9 271 }; 272 273 SBFullHash full_hash1, full_hash2; 274 for (int i = 0; i < 32; ++i) { 275 full_hash1.full_hash[i] = i % 2 ? '1' : '0'; 276 full_hash2.full_hash[i] = i % 2 ? '3' : '2'; 277 } 278 279 ScopedVector<SBChunkData> chunks; 280 EXPECT_TRUE(safe_browsing::ParseChunk(kRawSubChunk, sizeof(kRawSubChunk), 281 &chunks)); 282 ASSERT_EQ(1U, chunks.size()); 283 EXPECT_EQ(2, chunks[0]->ChunkNumber()); 284 EXPECT_FALSE(chunks[0]->IsAdd()); 285 EXPECT_TRUE(chunks[0]->IsSub()); 286 EXPECT_FALSE(chunks[0]->IsPrefix()); 287 EXPECT_TRUE(chunks[0]->IsFullHash()); 288 289 ASSERT_EQ(2U, chunks[0]->FullHashCount()); 290 EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(0), full_hash1)); 291 EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0)); 292 EXPECT_TRUE(SBFullHashEqual(chunks[0]->FullHashAt(1), full_hash2)); 293 EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1)); 294 } 295 296 // Test parsing the SafeBrowsing update response. 297 TEST(SafeBrowsingProtocolParsingTest, TestChunkDelete) { 298 std::string add_del("n:1700\ni:phishy\nad:1-7,43-597,44444,99999\n" 299 "i:malware\nsd:21-27,42,171717\n"); 300 301 size_t next_query_sec = 0; 302 bool reset = false; 303 std::vector<SBChunkDelete> deletes; 304 std::vector<ChunkUrl> urls; 305 EXPECT_TRUE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(), 306 &next_query_sec, &reset, 307 &deletes, &urls)); 308 309 EXPECT_TRUE(urls.empty()); 310 EXPECT_FALSE(reset); 311 EXPECT_EQ(1700U, next_query_sec); 312 ASSERT_EQ(2U, deletes.size()); 313 314 ASSERT_EQ(4U, deletes[0].chunk_del.size()); 315 EXPECT_TRUE(deletes[0].chunk_del[0] == ChunkRange(1, 7)); 316 EXPECT_TRUE(deletes[0].chunk_del[1] == ChunkRange(43, 597)); 317 EXPECT_TRUE(deletes[0].chunk_del[2] == ChunkRange(44444)); 318 EXPECT_TRUE(deletes[0].chunk_del[3] == ChunkRange(99999)); 319 320 ASSERT_EQ(3U, deletes[1].chunk_del.size()); 321 EXPECT_TRUE(deletes[1].chunk_del[0] == ChunkRange(21, 27)); 322 EXPECT_TRUE(deletes[1].chunk_del[1] == ChunkRange(42)); 323 EXPECT_TRUE(deletes[1].chunk_del[2] == ChunkRange(171717)); 324 325 // An update response with missing list name. 326 next_query_sec = 0; 327 deletes.clear(); 328 urls.clear(); 329 add_del = "n:1700\nad:1-7,43-597,44444,99999\ni:malware\nsd:4,21-27171717\n"; 330 EXPECT_FALSE(safe_browsing::ParseUpdate(add_del.data(), add_del.length(), 331 &next_query_sec, &reset, 332 &deletes, &urls)); 333 } 334 335 // Test parsing the SafeBrowsing update response. 336 TEST(SafeBrowsingProtocolParsingTest, TestRedirects) { 337 const std::string redirects(base::StringPrintf( 338 "i:%s\n" 339 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1\n" 340 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2\n" 341 "u:cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3\n" 342 "u:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:8641-8689," 343 "8691-8731,8733-8786\n", 344 kDefaultMalwareList)); 345 346 size_t next_query_sec = 0; 347 bool reset = false; 348 std::vector<SBChunkDelete> deletes; 349 std::vector<ChunkUrl> urls; 350 EXPECT_TRUE(safe_browsing::ParseUpdate(redirects.data(), redirects.length(), 351 &next_query_sec, &reset, 352 &deletes, &urls)); 353 EXPECT_FALSE(reset); 354 EXPECT_EQ(0U, next_query_sec); 355 EXPECT_TRUE(deletes.empty()); 356 357 ASSERT_EQ(4U, urls.size()); 358 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_1", 359 urls[0].url); 360 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_2", 361 urls[1].url); 362 EXPECT_EQ("cache.googlevideo.com/safebrowsing/rd/goog-malware-shavar_s_3", 363 urls[2].url); 364 EXPECT_EQ("s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_8641-8800:" 365 "8641-8689,8691-8731,8733-8786", 366 urls[3].url); 367 } 368 369 // Test parsing various SafeBrowsing protocol headers. 370 TEST(SafeBrowsingProtocolParsingTest, TestNextQueryTime) { 371 std::string headers("n:1800\ni:goog-white-shavar\n"); 372 size_t next_query_sec = 0; 373 bool reset = false; 374 std::vector<SBChunkDelete> deletes; 375 std::vector<ChunkUrl> urls; 376 EXPECT_TRUE(safe_browsing::ParseUpdate(headers.data(), headers.length(), 377 &next_query_sec, &reset, 378 &deletes, &urls)); 379 380 EXPECT_EQ(1800U, next_query_sec); 381 EXPECT_FALSE(reset); 382 EXPECT_TRUE(deletes.empty()); 383 EXPECT_TRUE(urls.empty()); 384 } 385 386 // Test parsing data from a GetHashRequest 387 TEST(SafeBrowsingProtocolParsingTest, TestGetHash) { 388 const std::string get_hash(base::StringPrintf( 389 "45\n" 390 "%s:32:3\n" 391 "00112233445566778899aabbccddeeff" 392 "00001111222233334444555566667777" 393 "ffffeeeeddddccccbbbbaaaa99998888", 394 kDefaultPhishList)); 395 std::vector<SBFullHashResult> full_hashes; 396 base::TimeDelta cache_lifetime; 397 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash.data(), get_hash.length(), 398 &cache_lifetime, &full_hashes)); 399 400 ASSERT_EQ(3U, full_hashes.size()); 401 EXPECT_EQ(memcmp(&full_hashes[0].hash, 402 "00112233445566778899aabbccddeeff", 403 sizeof(SBFullHash)), 0); 404 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); 405 EXPECT_EQ(memcmp(&full_hashes[1].hash, 406 "00001111222233334444555566667777", 407 sizeof(SBFullHash)), 0); 408 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[1].list_id); 409 EXPECT_EQ(memcmp(&full_hashes[2].hash, 410 "ffffeeeeddddccccbbbbaaaa99998888", 411 sizeof(SBFullHash)), 0); 412 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id); 413 414 // Test multiple lists in the GetHash results. 415 const std::string get_hash2(base::StringPrintf( 416 "45\n" 417 "%s:32:1\n" 418 "00112233445566778899aabbccddeeff" 419 "%s:32:2\n" 420 "cafebeefcafebeefdeaddeaddeaddead" 421 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", 422 kDefaultPhishList, 423 kDefaultMalwareList)); 424 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash2.data(), get_hash2.length(), 425 &cache_lifetime, &full_hashes)); 426 427 ASSERT_EQ(3U, full_hashes.size()); 428 EXPECT_EQ(memcmp(&full_hashes[0].hash, 429 "00112233445566778899aabbccddeeff", 430 sizeof(SBFullHash)), 0); 431 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); 432 EXPECT_EQ(memcmp(&full_hashes[1].hash, 433 "cafebeefcafebeefdeaddeaddeaddead", 434 sizeof(SBFullHash)), 0); 435 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); 436 EXPECT_EQ(memcmp(&full_hashes[2].hash, 437 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", 438 sizeof(SBFullHash)), 0); 439 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[2].list_id); 440 441 // Test metadata parsing. 442 const std::string get_hash3(base::StringPrintf( 443 "45\n" 444 "%s:32:2:m\n" 445 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss" 446 "00112233445566778899aabbccddeeff" 447 "2\nab2\nxy" 448 "%s:32:1\n" 449 "cafebeefcafebeefdeaddeaddeaddead", 450 kDefaultMalwareList, 451 kDefaultPhishList)); 452 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3.data(), get_hash3.length(), 453 &cache_lifetime, &full_hashes)); 454 455 ASSERT_EQ(3U, full_hashes.size()); 456 EXPECT_EQ(memcmp(&full_hashes[0].hash, 457 "zzzzyyyyxxxxwwwwvvvvuuuuttttssss", 458 sizeof(SBFullHash)), 0); 459 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id); 460 EXPECT_EQ(std::string("ab"), full_hashes[0].metadata); 461 EXPECT_EQ(memcmp(&full_hashes[1].hash, 462 "00112233445566778899aabbccddeeff", 463 sizeof(SBFullHash)), 0); 464 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); 465 EXPECT_EQ(std::string("xy"), full_hashes[1].metadata); 466 EXPECT_EQ(memcmp(&full_hashes[2].hash, 467 "cafebeefcafebeefdeaddeaddeaddead", 468 sizeof(SBFullHash)), 0); 469 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[2].list_id); 470 EXPECT_EQ(std::string(), full_hashes[2].metadata); 471 } 472 473 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownList) { 474 std::string hash_response(base::StringPrintf( 475 "45\n" 476 "%s:32:1\n" 477 "12345678901234567890123456789012" 478 "googpub-phish-shavar:32:1\n" 479 "09876543210987654321098765432109", 480 kDefaultPhishList)); 481 std::vector<SBFullHashResult> full_hashes; 482 base::TimeDelta cache_lifetime; 483 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(), 484 hash_response.size(), 485 &cache_lifetime, 486 &full_hashes)); 487 488 ASSERT_EQ(1U, full_hashes.size()); 489 EXPECT_EQ(memcmp("12345678901234567890123456789012", 490 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 491 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); 492 493 hash_response += base::StringPrintf( 494 "%s:32:1\n" 495 "abcdefghijklmnopqrstuvwxyz123457", 496 kDefaultMalwareList); 497 full_hashes.clear(); 498 EXPECT_TRUE(safe_browsing::ParseGetHash(hash_response.data(), 499 hash_response.size(), 500 &cache_lifetime, 501 &full_hashes)); 502 503 EXPECT_EQ(2U, full_hashes.size()); 504 EXPECT_EQ(memcmp("12345678901234567890123456789012", 505 &full_hashes[0].hash, sizeof(SBFullHash)), 0); 506 EXPECT_EQ(safe_browsing_util::PHISH, full_hashes[0].list_id); 507 EXPECT_EQ(memcmp("abcdefghijklmnopqrstuvwxyz123457", 508 &full_hashes[1].hash, sizeof(SBFullHash)), 0); 509 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[1].list_id); 510 } 511 512 TEST(SafeBrowsingProtocolParsingTest, TestGetHashWithUnknownListAndMetadata) { 513 std::vector<SBFullHashResult> full_hashes; 514 base::TimeDelta cache_lifetime; 515 // Test skipping over a hashentry with an unrecognized listname that also has 516 // metadata. 517 const std::string get_hash3(base::StringPrintf( 518 "600\n" 519 "BADLISTNAME:32:1:m\n" 520 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 521 "8\nMETADATA" 522 "%s:32:1\n" 523 "0123456789hashhashhashhashhashha", 524 kDefaultMalwareList)); 525 EXPECT_TRUE(safe_browsing::ParseGetHash(get_hash3.data(), get_hash3.length(), 526 &cache_lifetime, &full_hashes)); 527 ASSERT_EQ(1U, full_hashes.size()); 528 EXPECT_EQ(memcmp(&full_hashes[0].hash, 529 "0123456789hashhashhashhashhashha", 530 sizeof(SBFullHash)), 0); 531 EXPECT_EQ(safe_browsing_util::MALWARE, full_hashes[0].list_id); 532 EXPECT_EQ(std::string(), full_hashes[0].metadata); 533 } 534 535 TEST(SafeBrowsingProtocolParsingTest, TestFormatHash) { 536 std::vector<SBPrefix> prefixes; 537 prefixes.push_back(0x34333231); 538 prefixes.push_back(0x64636261); 539 prefixes.push_back(0x73727170); 540 541 EXPECT_EQ("4:12\n1234abcdpqrs", safe_browsing::FormatGetHash(prefixes)); 542 } 543 544 TEST(SafeBrowsingProtocolParsingTest, TestReset) { 545 std::string update("n:1800\ni:phishy\nr:pleasereset\n"); 546 547 bool reset = false; 548 size_t next_update = 0; 549 std::vector<SBChunkDelete> deletes; 550 std::vector<ChunkUrl> urls; 551 EXPECT_TRUE(safe_browsing::ParseUpdate(update.data(), update.size(), 552 &next_update, &reset, 553 &deletes, &urls)); 554 EXPECT_TRUE(reset); 555 } 556 557 // The SafeBrowsing service will occasionally send zero length chunks so that 558 // client requests will have longer contiguous chunk number ranges, and thus 559 // reduce the request size. 560 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeAddChunk) { 561 const char kEmptyAddChunk[] = { 562 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order. 563 '\x08', // field 1, wire format varint 564 '\x02', // chunk_number varint 2 565 }; 566 567 ScopedVector<SBChunkData> chunks; 568 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptyAddChunk, sizeof(kEmptyAddChunk), 569 &chunks)); 570 ASSERT_EQ(1U, chunks.size()); 571 EXPECT_EQ(2, chunks[0]->ChunkNumber()); 572 EXPECT_TRUE(chunks[0]->IsAdd()); 573 EXPECT_FALSE(chunks[0]->IsSub()); 574 EXPECT_TRUE(chunks[0]->IsPrefix()); 575 EXPECT_FALSE(chunks[0]->IsFullHash()); 576 EXPECT_EQ(0U, chunks[0]->PrefixCount()); 577 578 // Now test a zero size chunk in between normal chunks. 579 chunks.clear(); 580 const char kAddChunks[] = { 581 '\0', '\0', '\0', '\x0C', // 32-bit payload length in network byte order. 582 '\x08', // field 1, wire format varint 583 '\x01', // chunk_number varint 1 584 '\x22', // field 4, wire format length-delimited 585 '\x08', // varint length 8 586 587 '1', '1', '1', '1', // 4-byte prefixes 588 '2', '2', '2', '2', 589 590 '\0', '\0', '\0', '\x02', // 32-bit payload length in network byte order. 591 '\x08', // field 1, wire format varint 592 '\x02', // chunk_number varint 2 593 594 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order. 595 '\x08', // field 1, wire format varint 596 '\x03', // chunk_number varint 3 597 '\x22', // field 4, wire format length-delimited 598 '\x04', // varint length 8 599 'p', 'p', 'p', 'p', // 4-byte prefixes 600 }; 601 EXPECT_TRUE(safe_browsing::ParseChunk(kAddChunks, sizeof(kAddChunks), 602 &chunks)); 603 ASSERT_EQ(3U, chunks.size()); 604 605 EXPECT_EQ(1, chunks[0]->ChunkNumber()); 606 EXPECT_TRUE(chunks[0]->IsAdd()); 607 EXPECT_FALSE(chunks[0]->IsSub()); 608 EXPECT_TRUE(chunks[0]->IsPrefix()); 609 EXPECT_FALSE(chunks[0]->IsFullHash()); 610 ASSERT_EQ(2U, chunks[0]->PrefixCount()); 611 EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0)); // 1111 612 EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1)); // 2222 613 614 EXPECT_EQ(2, chunks[1]->ChunkNumber()); 615 EXPECT_TRUE(chunks[1]->IsAdd()); 616 EXPECT_FALSE(chunks[1]->IsSub()); 617 EXPECT_TRUE(chunks[1]->IsPrefix()); 618 EXPECT_FALSE(chunks[1]->IsFullHash()); 619 EXPECT_EQ(0U, chunks[1]->PrefixCount()); 620 621 EXPECT_EQ(3, chunks[2]->ChunkNumber()); 622 EXPECT_TRUE(chunks[2]->IsAdd()); 623 EXPECT_FALSE(chunks[2]->IsSub()); 624 EXPECT_TRUE(chunks[2]->IsPrefix()); 625 EXPECT_FALSE(chunks[2]->IsFullHash()); 626 ASSERT_EQ(1U, chunks[2]->PrefixCount()); 627 EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0)); // pppp 628 } 629 630 // Test parsing a zero sized sub chunk. 631 TEST(SafeBrowsingProtocolParsingTest, TestZeroSizeSubChunk) { 632 const char kEmptySubChunk[] = { 633 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order. 634 '\x08', // field 1, wire format varint 635 '\x02', // chunk_number varint 2 636 '\x10', // field 2, wire format varint 637 '\x01', // enum ChunkType == SUB 638 }; 639 640 ScopedVector<SBChunkData> chunks; 641 EXPECT_TRUE(safe_browsing::ParseChunk(kEmptySubChunk, sizeof(kEmptySubChunk), 642 &chunks)); 643 ASSERT_EQ(1U, chunks.size()); 644 EXPECT_EQ(2, chunks[0]->ChunkNumber()); 645 EXPECT_FALSE(chunks[0]->IsAdd()); 646 EXPECT_TRUE(chunks[0]->IsSub()); 647 EXPECT_TRUE(chunks[0]->IsPrefix()); 648 EXPECT_FALSE(chunks[0]->IsFullHash()); 649 EXPECT_EQ(0U, chunks[0]->PrefixCount()); 650 651 // Test parsing a zero sized sub chunk mixed in with content carrying chunks. 652 chunks.clear(); 653 const char kSubChunks[] = { 654 '\0', '\0', '\0', '\x12', // 32-bit payload length in network byte order. 655 '\x08', // field 1, wire format varint 656 '\x01', // chunk_number varint 1 657 '\x10', // field 2, wire format varint 658 '\x01', // enum ChunkType == SUB 659 '\x22', // field 4, wire format length-delimited 660 '\x08', // varint length 8 661 '1', '1', '1', '1', // 4-byte prefixes 662 '2', '2', '2', '2', 663 '\x2a', // field 5, wire format length-delimited 664 '\x02', // varint length 2 (2 add-chunk numbers) 665 '\x07', '\x09', // varint 7, varint 9 666 667 '\0', '\0', '\0', '\x04', // 32-bit payload length in network byte order. 668 '\x08', // field 1, wire format varint 669 '\x02', // chunk_number varint 2 670 '\x10', // field 2, wire format varint 671 '\x01', // enum ChunkType == SUB 672 673 '\0', '\0', '\0', '\x0D', // 32-bit payload length in network byte order. 674 '\x08', // field 1, wire format varint 675 '\x03', // chunk_number varint 3 676 '\x10', // field 2, wire format varint 677 '\x01', // enum ChunkType == SUB 678 '\x22', // field 4, wire format length-delimited 679 '\x04', // varint length 8 680 'p', 'p', 'p', 'p', // 4-byte prefix 681 '\x2a', // field 5, wire format length-delimited 682 '\x01', // varint length 1 (1 add-chunk numbers) 683 '\x0B', // varint 11 684 }; 685 686 EXPECT_TRUE(safe_browsing::ParseChunk(kSubChunks, sizeof(kSubChunks), 687 &chunks)); 688 ASSERT_EQ(3U, chunks.size()); 689 690 EXPECT_EQ(1, chunks[0]->ChunkNumber()); 691 EXPECT_FALSE(chunks[0]->IsAdd()); 692 EXPECT_TRUE(chunks[0]->IsSub()); 693 EXPECT_TRUE(chunks[0]->IsPrefix()); 694 EXPECT_FALSE(chunks[0]->IsFullHash()); 695 ASSERT_EQ(2U, chunks[0]->PrefixCount()); 696 EXPECT_EQ(0x31313131U, chunks[0]->PrefixAt(0)); // 1111 697 EXPECT_EQ(7, chunks[0]->AddChunkNumberAt(0)); 698 EXPECT_EQ(0x32323232U, chunks[0]->PrefixAt(1)); // 2222 699 EXPECT_EQ(9, chunks[0]->AddChunkNumberAt(1)); 700 701 EXPECT_EQ(2, chunks[1]->ChunkNumber()); 702 EXPECT_FALSE(chunks[0]->IsAdd()); 703 EXPECT_TRUE(chunks[0]->IsSub()); 704 EXPECT_TRUE(chunks[1]->IsPrefix()); 705 EXPECT_FALSE(chunks[1]->IsFullHash()); 706 EXPECT_EQ(0U, chunks[1]->PrefixCount()); 707 708 EXPECT_EQ(3, chunks[2]->ChunkNumber()); 709 EXPECT_FALSE(chunks[0]->IsAdd()); 710 EXPECT_TRUE(chunks[0]->IsSub()); 711 EXPECT_TRUE(chunks[2]->IsPrefix()); 712 EXPECT_FALSE(chunks[2]->IsFullHash()); 713 ASSERT_EQ(1U, chunks[2]->PrefixCount()); 714 EXPECT_EQ(0x70707070U, chunks[2]->PrefixAt(0)); // pppp 715 EXPECT_EQ(11, chunks[2]->AddChunkNumberAt(0)); 716 } 717 718 } // namespace 719