mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	Depends on D174432 Differential Revision: https://phabricator.services.mozilla.com/D174433
		
			
				
	
	
		
			140 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "mozilla/EndianUtils.h"
 | 
						|
#include "ProtocolParser.h"
 | 
						|
 | 
						|
#include "Common.h"
 | 
						|
 | 
						|
typedef FetchThreatListUpdatesResponse_ListUpdateResponse ListUpdateResponse;
 | 
						|
 | 
						|
static bool InitUpdateResponse(ListUpdateResponse* aUpdateResponse,
 | 
						|
                               ThreatType aThreatType, const nsACString& aState,
 | 
						|
                               const nsACString& aChecksum, bool isFullUpdate,
 | 
						|
                               const nsTArray<uint32_t>& aFixedLengthPrefixes,
 | 
						|
                               bool aDoPrefixEncoding) {
 | 
						|
  aUpdateResponse->set_threat_type(aThreatType);
 | 
						|
  aUpdateResponse->set_new_client_state(aState.BeginReading(), aState.Length());
 | 
						|
  aUpdateResponse->mutable_checksum()->set_sha256(aChecksum.BeginReading(),
 | 
						|
                                                  aChecksum.Length());
 | 
						|
  aUpdateResponse->set_response_type(isFullUpdate
 | 
						|
                                         ? ListUpdateResponse::FULL_UPDATE
 | 
						|
                                         : ListUpdateResponse::PARTIAL_UPDATE);
 | 
						|
 | 
						|
  auto additions = aUpdateResponse->mutable_additions()->Add();
 | 
						|
 | 
						|
  if (!aDoPrefixEncoding) {
 | 
						|
    additions->set_compression_type(RAW);
 | 
						|
    auto rawHashes = additions->mutable_raw_hashes();
 | 
						|
    rawHashes->set_prefix_size(4);
 | 
						|
    auto prefixes = rawHashes->mutable_raw_hashes();
 | 
						|
    for (auto p : aFixedLengthPrefixes) {
 | 
						|
      char buffer[4];
 | 
						|
      mozilla::NativeEndian::copyAndSwapToBigEndian(buffer, &p, 1);
 | 
						|
      prefixes->append(buffer, 4);
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (1 != aFixedLengthPrefixes.Length()) {
 | 
						|
    printf("This function only supports single value encoding.\n");
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t firstValue = aFixedLengthPrefixes[0];
 | 
						|
  additions->set_compression_type(RICE);
 | 
						|
  auto riceHashes = additions->mutable_rice_hashes();
 | 
						|
  riceHashes->set_first_value(firstValue);
 | 
						|
  riceHashes->set_num_entries(0);
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
static void DumpBinary(const nsACString& aBinary) {
 | 
						|
  nsCString s;
 | 
						|
  for (size_t i = 0; i < aBinary.Length(); i++) {
 | 
						|
    s.AppendPrintf("\\x%.2X", (uint8_t)aBinary[i]);
 | 
						|
  }
 | 
						|
  printf("%s\n", s.get());
 | 
						|
}
 | 
						|
 | 
						|
TEST(UrlClassifierProtocolParser, UpdateWait)
 | 
						|
{
 | 
						|
  // Top level response which contains a list of update response
 | 
						|
  // for different lists.
 | 
						|
  FetchThreatListUpdatesResponse response;
 | 
						|
 | 
						|
  auto r = response.mutable_list_update_responses()->Add();
 | 
						|
  InitUpdateResponse(r, SOCIAL_ENGINEERING_PUBLIC, nsCString("sta\x00te", 6),
 | 
						|
                     nsCString("check\x0sum", 9), true, {0, 1, 2, 3},
 | 
						|
                     false /* aDoPrefixEncoding */);
 | 
						|
 | 
						|
  // Set min wait duration.
 | 
						|
  auto minWaitDuration = response.mutable_minimum_wait_duration();
 | 
						|
  minWaitDuration->set_seconds(8);
 | 
						|
  minWaitDuration->set_nanos(1 * 1000000000);
 | 
						|
 | 
						|
  std::string s;
 | 
						|
  response.SerializeToString(&s);
 | 
						|
 | 
						|
  DumpBinary(nsCString(s.c_str(), s.length()));
 | 
						|
 | 
						|
  ProtocolParser* p = new ProtocolParserProtobuf();
 | 
						|
  p->AppendStream(nsCString(s.c_str(), s.length()));
 | 
						|
  p->End();
 | 
						|
  ASSERT_EQ(p->UpdateWaitSec(), 9u);
 | 
						|
  delete p;
 | 
						|
}
 | 
						|
 | 
						|
TEST(UrlClassifierProtocolParser, SingleValueEncoding)
 | 
						|
{
 | 
						|
  // Top level response which contains a list of update response
 | 
						|
  // for different lists.
 | 
						|
  FetchThreatListUpdatesResponse response;
 | 
						|
 | 
						|
  auto r = response.mutable_list_update_responses()->Add();
 | 
						|
 | 
						|
  const char* expectedPrefix = "\x00\x01\x02\x00";
 | 
						|
  if (!InitUpdateResponse(r, SOCIAL_ENGINEERING_PUBLIC,
 | 
						|
                          nsCString("sta\x00te", 6),
 | 
						|
                          nsCString("check\x0sum", 9), true,
 | 
						|
                          // As per spec, we should interpret the prefix as
 | 
						|
                          // uint32 in little endian before encoding.
 | 
						|
                          {mozilla::LittleEndian::readUint32(expectedPrefix)},
 | 
						|
                          true /* aDoPrefixEncoding */)) {
 | 
						|
    printf("Failed to initialize update response.");
 | 
						|
    ASSERT_TRUE(false);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // Set min wait duration.
 | 
						|
  auto minWaitDuration = response.mutable_minimum_wait_duration();
 | 
						|
  minWaitDuration->set_seconds(8);
 | 
						|
  minWaitDuration->set_nanos(1 * 1000000000);
 | 
						|
 | 
						|
  std::string s;
 | 
						|
  response.SerializeToString(&s);
 | 
						|
 | 
						|
  // Feed data to the protocol parser.
 | 
						|
  ProtocolParser* p = new ProtocolParserProtobuf();
 | 
						|
  p->SetRequestedTables({nsCString("googpub-phish-proto")});
 | 
						|
  p->AppendStream(nsCString(s.c_str(), s.length()));
 | 
						|
  p->End();
 | 
						|
 | 
						|
  const TableUpdateArray& tus = p->GetTableUpdates();
 | 
						|
  RefPtr<const TableUpdateV4> tuv4 = TableUpdate::Cast<TableUpdateV4>(tus[0]);
 | 
						|
  auto& prefixMap = tuv4->Prefixes();
 | 
						|
  for (const auto& entry : prefixMap) {
 | 
						|
    // This prefix map should contain only a single 4-byte prefixe.
 | 
						|
    ASSERT_EQ(entry.GetKey(), 4u);
 | 
						|
 | 
						|
    // The fixed-length prefix string from ProtocolParser should
 | 
						|
    // exactly match the expected prefix string.
 | 
						|
    nsCString* prefix = entry.GetWeak();
 | 
						|
    ASSERT_TRUE(prefix->Equals(nsCString(expectedPrefix, 4)));
 | 
						|
  }
 | 
						|
 | 
						|
  delete p;
 | 
						|
}
 |