2012-08-15 11:04:19 +04:00
|
|
|
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-08-15 11:10:56 +04:00
|
|
|
/* 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/. */
|
2012-08-15 11:04:19 +04:00
|
|
|
|
|
|
|
#ifndef ProtocolParser_h__
|
|
|
|
#define ProtocolParser_h__
|
|
|
|
|
|
|
|
#include "HashStore.h"
|
2017-10-13 03:27:36 +03:00
|
|
|
#include "chromium/safebrowsing.pb.h"
|
2012-08-15 11:04:19 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace safebrowsing {
|
|
|
|
|
|
|
|
/**
|
2016-08-12 06:55:48 +03:00
|
|
|
* Abstract base class for parsing update data in multiple formats.
|
2012-08-15 11:04:19 +04:00
|
|
|
*/
|
|
|
|
class ProtocolParser {
|
|
|
|
public:
|
|
|
|
struct ForwardedUpdate {
|
|
|
|
nsCString table;
|
|
|
|
nsCString url;
|
|
|
|
};
|
|
|
|
|
2013-01-08 19:43:33 +04:00
|
|
|
ProtocolParser();
|
2016-08-04 13:10:12 +03:00
|
|
|
virtual ~ProtocolParser();
|
2012-08-15 11:04:19 +04:00
|
|
|
|
|
|
|
nsresult Status() const { return mUpdateStatus; }
|
|
|
|
|
2016-10-14 12:58:18 +03:00
|
|
|
#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
|
2017-01-19 12:16:13 +03:00
|
|
|
virtual nsCString GetRawTableUpdates() const { return mPending; }
|
2016-10-14 12:58:18 +03:00
|
|
|
#endif
|
|
|
|
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual void SetCurrentTable(const nsACString& aTable) = 0;
|
2012-08-15 11:04:19 +04:00
|
|
|
|
2016-08-16 12:30:11 +03:00
|
|
|
void SetRequestedTables(const nsTArray<nsCString>& aRequestTables)
|
|
|
|
{
|
|
|
|
mRequestedTables = aRequestTables;
|
|
|
|
}
|
|
|
|
|
2018-04-24 11:08:56 +03:00
|
|
|
nsresult Begin(const nsACString& aTable,
|
|
|
|
const nsTArray<nsCString>& aUpdateTables);
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual nsresult AppendStream(const nsACString& aData) = 0;
|
2016-08-04 13:10:12 +03:00
|
|
|
|
2016-10-18 09:45:21 +03:00
|
|
|
uint32_t UpdateWaitSec() { return mUpdateWaitSec; }
|
|
|
|
|
2016-08-04 13:10:12 +03:00
|
|
|
// Notify that the inbound data is ready for parsing if progressive
|
|
|
|
// parsing is not supported, for example in V4.
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual void End() = 0;
|
2012-08-15 11:04:19 +04:00
|
|
|
|
|
|
|
// 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; }
|
|
|
|
|
2016-08-12 06:55:48 +03:00
|
|
|
// These are only meaningful to V2. Since they were originally public,
|
|
|
|
// moving them to ProtocolParserV2 requires a dymamic cast in the call
|
2016-10-18 09:45:21 +03:00
|
|
|
// sites. As a result, we will leave them until we remove support
|
2016-08-16 12:30:11 +03:00
|
|
|
// for V2 entirely..
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual const nsTArray<ForwardedUpdate> &Forwards() const { return mForwards; }
|
2018-04-12 20:11:30 +03:00
|
|
|
bool ResetRequested() const { return !mTablesToReset.IsEmpty(); }
|
|
|
|
const nsTArray<nsCString>& TablesToReset() const { return mTablesToReset; }
|
2016-08-12 06:55:48 +03:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-08-16 12:30:11 +03:00
|
|
|
// The table names that were requested from the client.
|
|
|
|
nsTArray<nsCString> mRequestedTables;
|
|
|
|
|
2018-04-12 20:11:30 +03:00
|
|
|
// The table names that failed to update and need to be reset.
|
|
|
|
nsTArray<nsCString> mTablesToReset;
|
|
|
|
|
2016-10-18 09:45:21 +03:00
|
|
|
// How long we should wait until the next update.
|
|
|
|
uint32_t mUpdateWaitSec;
|
|
|
|
|
2016-08-12 06:55:48 +03:00
|
|
|
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;
|
|
|
|
|
2012-08-15 11:04:19 +04:00
|
|
|
// Update information.
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual const nsTArray<ForwardedUpdate> &Forwards() const override { return mForwards; }
|
2012-08-15 11:04:19 +04:00
|
|
|
|
2017-01-19 12:16:13 +03:00
|
|
|
#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
|
|
|
|
// Unfortunately we have to override to return mRawUpdate which
|
|
|
|
// will not be modified during the parsing, unlike mPending.
|
|
|
|
virtual nsCString GetRawTableUpdates() const override { return mRawUpdate; }
|
|
|
|
#endif
|
|
|
|
|
2012-08-15 11:04:19 +04:00
|
|
|
private:
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
|
|
|
|
|
2012-08-15 11:04:19 +04:00
|
|
|
nsresult ProcessControl(bool* aDone);
|
|
|
|
nsresult ProcessExpirations(const nsCString& aLine);
|
|
|
|
nsresult ProcessChunkControl(const nsCString& aLine);
|
|
|
|
nsresult ProcessForward(const nsCString& aLine);
|
2014-01-16 12:27:58 +04:00
|
|
|
nsresult AddForward(const nsACString& aUrl);
|
2012-08-15 11:04:19 +04:00
|
|
|
nsresult ProcessChunk(bool* done);
|
2013-09-07 04:12:33 +04:00
|
|
|
// Remove this, it's only used for testing
|
2012-08-15 11:04:19 +04:00
|
|
|
nsresult ProcessPlaintextChunk(const nsACString& aChunk);
|
|
|
|
nsresult ProcessShaChunk(const nsACString& aChunk);
|
2012-08-22 19:56:38 +04:00
|
|
|
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);
|
2013-09-07 04:12:33 +04:00
|
|
|
// 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);
|
2012-08-15 11:04:19 +04:00
|
|
|
bool NextLine(nsACString& aLine);
|
|
|
|
|
|
|
|
enum ParserState {
|
|
|
|
PROTOCOL_STATE_CONTROL,
|
|
|
|
PROTOCOL_STATE_CHUNK
|
|
|
|
};
|
|
|
|
ParserState mState;
|
|
|
|
|
|
|
|
enum ChunkType {
|
2013-09-07 04:12:33 +04:00
|
|
|
// Types for shavar tables.
|
2012-08-15 11:04:19 +04:00
|
|
|
CHUNK_ADD,
|
2013-09-07 04:12:33 +04:00
|
|
|
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
|
2012-08-15 11:04:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ChunkState {
|
|
|
|
ChunkType type;
|
2012-10-12 03:38:04 +04:00
|
|
|
uint32_t num;
|
|
|
|
uint32_t hashSize;
|
|
|
|
uint32_t length;
|
2012-08-15 11:04:19 +04:00
|
|
|
void Clear() { num = 0; hashSize = 0; length = 0; }
|
|
|
|
};
|
|
|
|
ChunkState mChunkState;
|
|
|
|
|
2013-09-07 04:12:33 +04:00
|
|
|
// Updates to apply to the current table being parsed.
|
2016-08-12 06:55:48 +03:00
|
|
|
TableUpdateV2 *mTableUpdate;
|
2017-01-19 12:16:13 +03:00
|
|
|
|
|
|
|
#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
|
|
|
|
nsCString mRawUpdate; // Keep a copy of mPending before it's processed.
|
|
|
|
#endif
|
2012-08-15 11:04:19 +04:00
|
|
|
};
|
|
|
|
|
2016-08-04 13:10:12 +03:00
|
|
|
// 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();
|
|
|
|
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual void SetCurrentTable(const nsACString& aTable) override;
|
2016-08-04 13:10:12 +03:00
|
|
|
virtual nsresult AppendStream(const nsACString& aData) override;
|
|
|
|
virtual void End() override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual ~ProtocolParserProtobuf();
|
|
|
|
|
2016-08-12 06:55:48 +03:00
|
|
|
virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
|
|
|
|
|
2016-08-04 13:10:12 +03:00
|
|
|
// For parsing update info.
|
2018-04-12 20:11:30 +03:00
|
|
|
nsresult ProcessOneResponse(const ListUpdateResponse& aResponse,
|
|
|
|
nsACString& aListName);
|
2016-08-12 06:55:48 +03:00
|
|
|
|
|
|
|
nsresult ProcessAdditionOrRemoval(TableUpdateV4& aTableUpdate,
|
|
|
|
const ThreatEntrySetList& aUpdate,
|
2016-08-04 13:10:12 +03:00
|
|
|
bool aIsAddition);
|
2016-08-12 06:55:48 +03:00
|
|
|
|
|
|
|
nsresult ProcessRawAddition(TableUpdateV4& aTableUpdate,
|
|
|
|
const ThreatEntrySet& aAddition);
|
|
|
|
|
|
|
|
nsresult ProcessRawRemoval(TableUpdateV4& aTableUpdate,
|
|
|
|
const ThreatEntrySet& aRemoval);
|
2016-10-05 09:59:53 +03:00
|
|
|
|
|
|
|
nsresult ProcessEncodedAddition(TableUpdateV4& aTableUpdate,
|
|
|
|
const ThreatEntrySet& aAddition);
|
|
|
|
|
|
|
|
nsresult ProcessEncodedRemoval(TableUpdateV4& aTableUpdate,
|
|
|
|
const ThreatEntrySet& aRemoval);
|
2016-08-04 13:10:12 +03:00
|
|
|
};
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace safebrowsing
|
|
|
|
} // namespace mozilla
|
2012-08-15 11:04:19 +04:00
|
|
|
|
|
|
|
#endif
|