123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- //* -*- 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/. */
- #ifndef ProtocolParser_h__
- #define ProtocolParser_h__
- #include "HashStore.h"
- #include "nsICryptoHMAC.h"
- #include "safebrowsing.pb.h"
- namespace mozilla {
- namespace safebrowsing {
- /**
- * Abstract base class for parsing update data in multiple formats.
- */
- class ProtocolParser {
- public:
- struct ForwardedUpdate {
- nsCString table;
- nsCString url;
- };
- ProtocolParser();
- virtual ~ProtocolParser();
- nsresult Status() const { return mUpdateStatus; }
- nsresult Init(nsICryptoHash* aHasher);
- #ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
- nsCString GetRawTableUpdates() const { return mPending; }
- #endif
- virtual void SetCurrentTable(const nsACString& aTable) = 0;
- void SetRequestedTables(const nsTArray<nsCString>& aRequestTables)
- {
- mRequestedTables = aRequestTables;
- }
- nsresult Begin();
- virtual nsresult AppendStream(const nsACString& aData) = 0;
- uint32_t UpdateWaitSec() { return mUpdateWaitSec; }
- // Notify that the inbound data is ready for parsing if progressive
- // parsing is not supported, for example in V4.
- virtual void End() = 0;
- // Forget the table updates that were created by this pass. It
- // becomes the caller's responsibility to free them. This is shitty.
- TableUpdate *GetTableUpdate(const nsACString& aTable);
- void ForgetTableUpdates() { mTableUpdates.Clear(); }
- nsTArray<TableUpdate*> &GetTableUpdates() { return mTableUpdates; }
- // These are only meaningful to V2. Since they were originally public,
- // moving them to ProtocolParserV2 requires a dymamic cast in the call
- // sites. As a result, we will leave them until we remove support
- // for V2 entirely..
- virtual const nsTArray<ForwardedUpdate> &Forwards() const { return mForwards; }
- virtual bool ResetRequested() { return false; }
- protected:
- virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const = 0;
- nsCString mPending;
- nsresult mUpdateStatus;
- // Keep track of updates to apply before passing them to the DBServiceWorkers.
- nsTArray<TableUpdate*> mTableUpdates;
- nsTArray<ForwardedUpdate> mForwards;
- nsCOMPtr<nsICryptoHash> mCryptoHash;
- // The table names that were requested from the client.
- nsTArray<nsCString> mRequestedTables;
- // How long we should wait until the next update.
- uint32_t mUpdateWaitSec;
- private:
- void CleanupUpdates();
- };
- /**
- * Helpers to parse the "shavar", "digest256" and "simple" list formats.
- */
- class ProtocolParserV2 final : public ProtocolParser {
- public:
- ProtocolParserV2();
- virtual ~ProtocolParserV2();
- virtual void SetCurrentTable(const nsACString& aTable) override;
- virtual nsresult AppendStream(const nsACString& aData) override;
- virtual void End() override;
- // Update information.
- virtual const nsTArray<ForwardedUpdate> &Forwards() const override { return mForwards; }
- virtual bool ResetRequested() override { return mResetRequested; }
- private:
- virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
- nsresult ProcessControl(bool* aDone);
- nsresult ProcessExpirations(const nsCString& aLine);
- nsresult ProcessChunkControl(const nsCString& aLine);
- nsresult ProcessForward(const nsCString& aLine);
- nsresult AddForward(const nsACString& aUrl);
- nsresult ProcessChunk(bool* done);
- // Remove this, it's only used for testing
- nsresult ProcessPlaintextChunk(const nsACString& aChunk);
- nsresult ProcessShaChunk(const nsACString& aChunk);
- nsresult ProcessHostAdd(const Prefix& aDomain, uint8_t aNumEntries,
- const nsACString& aChunk, uint32_t* aStart);
- nsresult ProcessHostSub(const Prefix& aDomain, uint8_t aNumEntries,
- const nsACString& aChunk, uint32_t* aStart);
- nsresult ProcessHostAddComplete(uint8_t aNumEntries, const nsACString& aChunk,
- uint32_t *aStart);
- nsresult ProcessHostSubComplete(uint8_t numEntries, const nsACString& aChunk,
- uint32_t* start);
- // Digest chunks are very similar to shavar chunks, except digest chunks
- // always contain the full hash, so there is no need for chunk data to
- // contain prefix sizes.
- nsresult ProcessDigestChunk(const nsACString& aChunk);
- nsresult ProcessDigestAdd(const nsACString& aChunk);
- nsresult ProcessDigestSub(const nsACString& aChunk);
- bool NextLine(nsACString& aLine);
- enum ParserState {
- PROTOCOL_STATE_CONTROL,
- PROTOCOL_STATE_CHUNK
- };
- ParserState mState;
- enum ChunkType {
- // Types for shavar tables.
- CHUNK_ADD,
- CHUNK_SUB,
- // Types for digest256 tables. digest256 tables differ in format from
- // shavar tables since they only contain complete hashes.
- CHUNK_ADD_DIGEST,
- CHUNK_SUB_DIGEST
- };
- struct ChunkState {
- ChunkType type;
- uint32_t num;
- uint32_t hashSize;
- uint32_t length;
- void Clear() { num = 0; hashSize = 0; length = 0; }
- };
- ChunkState mChunkState;
- bool mResetRequested;
- // Updates to apply to the current table being parsed.
- TableUpdateV2 *mTableUpdate;
- };
- // Helpers to parse the "proto" list format.
- class ProtocolParserProtobuf final : public ProtocolParser {
- public:
- typedef FetchThreatListUpdatesResponse_ListUpdateResponse ListUpdateResponse;
- typedef google::protobuf::RepeatedPtrField<ThreatEntrySet> ThreatEntrySetList;
- public:
- ProtocolParserProtobuf();
- virtual void SetCurrentTable(const nsACString& aTable) override;
- virtual nsresult AppendStream(const nsACString& aData) override;
- virtual void End() override;
- private:
- virtual ~ProtocolParserProtobuf();
- virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
- // For parsing update info.
- nsresult ProcessOneResponse(const ListUpdateResponse& aResponse);
- nsresult ProcessAdditionOrRemoval(TableUpdateV4& aTableUpdate,
- const ThreatEntrySetList& aUpdate,
- bool aIsAddition);
- nsresult ProcessRawAddition(TableUpdateV4& aTableUpdate,
- const ThreatEntrySet& aAddition);
- nsresult ProcessRawRemoval(TableUpdateV4& aTableUpdate,
- const ThreatEntrySet& aRemoval);
- nsresult ProcessEncodedAddition(TableUpdateV4& aTableUpdate,
- const ThreatEntrySet& aAddition);
- nsresult ProcessEncodedRemoval(TableUpdateV4& aTableUpdate,
- const ThreatEntrySet& aRemoval);
- };
- } // namespace safebrowsing
- } // namespace mozilla
- #endif
|