1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef mozilla_net_DNSPacket_h__ 6 #define mozilla_net_DNSPacket_h__ 7 8 #include "mozilla/Maybe.h" 9 #include "mozilla/Result.h" 10 #include "pk11pub.h" 11 #include "ScopedNSSTypes.h" 12 #include "nsClassHashtable.h" 13 #include "nsIDNSService.h" 14 #include "DNS.h" 15 #include "DNSByTypeRecord.h" 16 17 namespace mozilla { 18 namespace net { 19 20 class DOHresp { 21 public: 22 nsresult Add(uint32_t TTL, unsigned char const* dns, unsigned int index, 23 uint16_t len, bool aLocalAllowed); 24 nsTArray<NetAddr> mAddresses; 25 uint32_t mTtl = 0; 26 }; 27 28 // the values map to RFC1035 type identifiers 29 enum TrrType { 30 TRRTYPE_A = 1, 31 TRRTYPE_NS = 2, 32 TRRTYPE_CNAME = 5, 33 TRRTYPE_AAAA = 28, 34 TRRTYPE_OPT = 41, 35 TRRTYPE_TXT = 16, 36 TRRTYPE_HTTPSSVC = nsIDNSService::RESOLVE_TYPE_HTTPSSVC, // 65 37 }; 38 39 enum class DNSPacketStatus : uint8_t { 40 Unknown = 0, 41 Success, 42 KeyNotAvailable, 43 KeyNotUsable, 44 EncodeError, 45 EncryptError, 46 DecodeError, 47 DecryptError, 48 }; 49 50 class DNSPacket { 51 public: 52 DNSPacket() = default; 53 virtual ~DNSPacket() = default; 54 55 Result<uint8_t, nsresult> GetRCode() const; 56 57 // Called in order to feed data into the buffer. 58 nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream, 59 uint64_t aOffset, const uint32_t aCount); 60 61 // Encodes the name request into a buffer that represents a DNS packet 62 virtual nsresult EncodeRequest(nsCString& aBody, const nsACString& aHost, 63 uint16_t aType, bool aDisableECS); 64 65 // Decodes the DNS response and extracts the responses, additional records, 66 // etc. XXX: This should probably be refactored to reduce the number of 67 // output parameters and have a common format for different record types. 68 virtual nsresult Decode( 69 nsCString& aHost, enum TrrType aType, nsCString& aCname, 70 bool aAllowRFC1918, DOHresp& aResp, TypeRecordResultType& aTypeResult, 71 nsClassHashtable<nsCStringHashKey, DOHresp>& aAdditionalRecords, 72 uint32_t& aTTL); 73 PacketStatus()74 DNSPacketStatus PacketStatus() const { return mStatus; } 75 76 protected: 77 // Never accept larger DOH responses than this as that would indicate 78 // something is wrong. Typical ones are much smaller. 79 static const unsigned int MAX_SIZE = 3200; 80 81 nsresult PassQName(unsigned int& index, const unsigned char* aBuffer); 82 nsresult GetQname(nsACString& aQname, unsigned int& aIndex, 83 const unsigned char* aBuffer); 84 nsresult ParseSvcParam(unsigned int svcbIndex, uint16_t key, 85 SvcFieldValue& field, uint16_t length, 86 const unsigned char* aBuffer); 87 nsresult DecodeInternal( 88 nsCString& aHost, enum TrrType aType, nsCString& aCname, 89 bool aAllowRFC1918, DOHresp& aResp, TypeRecordResultType& aTypeResult, 90 nsClassHashtable<nsCStringHashKey, DOHresp>& aAdditionalRecords, 91 uint32_t& aTTL, const unsigned char* aBuffer, uint32_t aLen); 92 SetDNSPacketStatus(DNSPacketStatus aStatus)93 void SetDNSPacketStatus(DNSPacketStatus aStatus) { 94 if (mStatus == DNSPacketStatus::Unknown || 95 mStatus == DNSPacketStatus::Success) { 96 mStatus = aStatus; 97 } 98 } 99 100 // The response buffer. 101 unsigned char mResponse[MAX_SIZE]{}; 102 unsigned int mBodySize = 0; 103 DNSPacketStatus mStatus = DNSPacketStatus::Unknown; 104 }; 105 106 class ODoHDNSPacket final : public DNSPacket { 107 public: 108 ODoHDNSPacket() = default; 109 virtual ~ODoHDNSPacket(); 110 111 static bool ParseODoHConfigs(Span<const uint8_t> aData, 112 nsTArray<ObliviousDoHConfig>& aOut); 113 114 virtual nsresult EncodeRequest(nsCString& aBody, const nsACString& aHost, 115 uint16_t aType, bool aDisableECS) override; 116 117 virtual nsresult Decode( 118 nsCString& aHost, enum TrrType aType, nsCString& aCname, 119 bool aAllowRFC1918, DOHresp& aResp, TypeRecordResultType& aTypeResult, 120 nsClassHashtable<nsCStringHashKey, DOHresp>& aAdditionalRecords, 121 uint32_t& aTTL) override; 122 123 protected: 124 bool EncryptDNSQuery(const nsACString& aQuery, uint16_t aPaddingLen, 125 const ObliviousDoHConfig& aConfig, 126 ObliviousDoHMessage& aOut); 127 bool DecryptDNSResponse(); 128 129 HpkeContext* mContext = nullptr; 130 UniqueSECItem mPlainQuery; 131 // This struct indicates the range of decrypted responses stored in mResponse. 132 struct DecryptedResponseRange { 133 uint16_t mStart = 0; 134 uint16_t mLength = 0; 135 }; 136 Maybe<DecryptedResponseRange> mDecryptedResponseRange; 137 }; 138 139 } // namespace net 140 } // namespace mozilla 141 142 #endif // mozilla_net_DNSPacket_h__ 143