ProtocolParser.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef ProtocolParser_h__
  6. #define ProtocolParser_h__
  7. #include "HashStore.h"
  8. #include "nsICryptoHMAC.h"
  9. #include "safebrowsing.pb.h"
  10. namespace mozilla {
  11. namespace safebrowsing {
  12. /**
  13. * Abstract base class for parsing update data in multiple formats.
  14. */
  15. class ProtocolParser {
  16. public:
  17. struct ForwardedUpdate {
  18. nsCString table;
  19. nsCString url;
  20. };
  21. ProtocolParser();
  22. virtual ~ProtocolParser();
  23. nsresult Status() const { return mUpdateStatus; }
  24. nsresult Init(nsICryptoHash* aHasher);
  25. #ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
  26. nsCString GetRawTableUpdates() const { return mPending; }
  27. #endif
  28. virtual void SetCurrentTable(const nsACString& aTable) = 0;
  29. void SetRequestedTables(const nsTArray<nsCString>& aRequestTables)
  30. {
  31. mRequestedTables = aRequestTables;
  32. }
  33. nsresult Begin();
  34. virtual nsresult AppendStream(const nsACString& aData) = 0;
  35. uint32_t UpdateWaitSec() { return mUpdateWaitSec; }
  36. // Notify that the inbound data is ready for parsing if progressive
  37. // parsing is not supported, for example in V4.
  38. virtual void End() = 0;
  39. // Forget the table updates that were created by this pass. It
  40. // becomes the caller's responsibility to free them. This is shitty.
  41. TableUpdate *GetTableUpdate(const nsACString& aTable);
  42. void ForgetTableUpdates() { mTableUpdates.Clear(); }
  43. nsTArray<TableUpdate*> &GetTableUpdates() { return mTableUpdates; }
  44. // These are only meaningful to V2. Since they were originally public,
  45. // moving them to ProtocolParserV2 requires a dymamic cast in the call
  46. // sites. As a result, we will leave them until we remove support
  47. // for V2 entirely..
  48. virtual const nsTArray<ForwardedUpdate> &Forwards() const { return mForwards; }
  49. virtual bool ResetRequested() { return false; }
  50. protected:
  51. virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const = 0;
  52. nsCString mPending;
  53. nsresult mUpdateStatus;
  54. // Keep track of updates to apply before passing them to the DBServiceWorkers.
  55. nsTArray<TableUpdate*> mTableUpdates;
  56. nsTArray<ForwardedUpdate> mForwards;
  57. nsCOMPtr<nsICryptoHash> mCryptoHash;
  58. // The table names that were requested from the client.
  59. nsTArray<nsCString> mRequestedTables;
  60. // How long we should wait until the next update.
  61. uint32_t mUpdateWaitSec;
  62. private:
  63. void CleanupUpdates();
  64. };
  65. /**
  66. * Helpers to parse the "shavar", "digest256" and "simple" list formats.
  67. */
  68. class ProtocolParserV2 final : public ProtocolParser {
  69. public:
  70. ProtocolParserV2();
  71. virtual ~ProtocolParserV2();
  72. virtual void SetCurrentTable(const nsACString& aTable) override;
  73. virtual nsresult AppendStream(const nsACString& aData) override;
  74. virtual void End() override;
  75. // Update information.
  76. virtual const nsTArray<ForwardedUpdate> &Forwards() const override { return mForwards; }
  77. virtual bool ResetRequested() override { return mResetRequested; }
  78. private:
  79. virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
  80. nsresult ProcessControl(bool* aDone);
  81. nsresult ProcessExpirations(const nsCString& aLine);
  82. nsresult ProcessChunkControl(const nsCString& aLine);
  83. nsresult ProcessForward(const nsCString& aLine);
  84. nsresult AddForward(const nsACString& aUrl);
  85. nsresult ProcessChunk(bool* done);
  86. // Remove this, it's only used for testing
  87. nsresult ProcessPlaintextChunk(const nsACString& aChunk);
  88. nsresult ProcessShaChunk(const nsACString& aChunk);
  89. nsresult ProcessHostAdd(const Prefix& aDomain, uint8_t aNumEntries,
  90. const nsACString& aChunk, uint32_t* aStart);
  91. nsresult ProcessHostSub(const Prefix& aDomain, uint8_t aNumEntries,
  92. const nsACString& aChunk, uint32_t* aStart);
  93. nsresult ProcessHostAddComplete(uint8_t aNumEntries, const nsACString& aChunk,
  94. uint32_t *aStart);
  95. nsresult ProcessHostSubComplete(uint8_t numEntries, const nsACString& aChunk,
  96. uint32_t* start);
  97. // Digest chunks are very similar to shavar chunks, except digest chunks
  98. // always contain the full hash, so there is no need for chunk data to
  99. // contain prefix sizes.
  100. nsresult ProcessDigestChunk(const nsACString& aChunk);
  101. nsresult ProcessDigestAdd(const nsACString& aChunk);
  102. nsresult ProcessDigestSub(const nsACString& aChunk);
  103. bool NextLine(nsACString& aLine);
  104. enum ParserState {
  105. PROTOCOL_STATE_CONTROL,
  106. PROTOCOL_STATE_CHUNK
  107. };
  108. ParserState mState;
  109. enum ChunkType {
  110. // Types for shavar tables.
  111. CHUNK_ADD,
  112. CHUNK_SUB,
  113. // Types for digest256 tables. digest256 tables differ in format from
  114. // shavar tables since they only contain complete hashes.
  115. CHUNK_ADD_DIGEST,
  116. CHUNK_SUB_DIGEST
  117. };
  118. struct ChunkState {
  119. ChunkType type;
  120. uint32_t num;
  121. uint32_t hashSize;
  122. uint32_t length;
  123. void Clear() { num = 0; hashSize = 0; length = 0; }
  124. };
  125. ChunkState mChunkState;
  126. bool mResetRequested;
  127. // Updates to apply to the current table being parsed.
  128. TableUpdateV2 *mTableUpdate;
  129. };
  130. // Helpers to parse the "proto" list format.
  131. class ProtocolParserProtobuf final : public ProtocolParser {
  132. public:
  133. typedef FetchThreatListUpdatesResponse_ListUpdateResponse ListUpdateResponse;
  134. typedef google::protobuf::RepeatedPtrField<ThreatEntrySet> ThreatEntrySetList;
  135. public:
  136. ProtocolParserProtobuf();
  137. virtual void SetCurrentTable(const nsACString& aTable) override;
  138. virtual nsresult AppendStream(const nsACString& aData) override;
  139. virtual void End() override;
  140. private:
  141. virtual ~ProtocolParserProtobuf();
  142. virtual TableUpdate* CreateTableUpdate(const nsACString& aTableName) const override;
  143. // For parsing update info.
  144. nsresult ProcessOneResponse(const ListUpdateResponse& aResponse);
  145. nsresult ProcessAdditionOrRemoval(TableUpdateV4& aTableUpdate,
  146. const ThreatEntrySetList& aUpdate,
  147. bool aIsAddition);
  148. nsresult ProcessRawAddition(TableUpdateV4& aTableUpdate,
  149. const ThreatEntrySet& aAddition);
  150. nsresult ProcessRawRemoval(TableUpdateV4& aTableUpdate,
  151. const ThreatEntrySet& aRemoval);
  152. nsresult ProcessEncodedAddition(TableUpdateV4& aTableUpdate,
  153. const ThreatEntrySet& aAddition);
  154. nsresult ProcessEncodedRemoval(TableUpdateV4& aTableUpdate,
  155. const ThreatEntrySet& aRemoval);
  156. };
  157. } // namespace safebrowsing
  158. } // namespace mozilla
  159. #endif