diff options
Diffstat (limited to 'toolkit/components/url-classifier/ProtocolParser.h')
-rw-r--r-- | toolkit/components/url-classifier/ProtocolParser.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/toolkit/components/url-classifier/ProtocolParser.h b/toolkit/components/url-classifier/ProtocolParser.h new file mode 100644 index 000000000..ec1a695f4 --- /dev/null +++ b/toolkit/components/url-classifier/ProtocolParser.h @@ -0,0 +1,204 @@ +//* -*- 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 |