mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2025-04-12 21:51:01 +00:00
362 lines
12 KiB
C++
362 lines
12 KiB
C++
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef NET_DNS_RECORD_RDATA_H_
|
|
#define NET_DNS_RECORD_RDATA_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "base/check_op.h"
|
|
#include "base/compiler_specific.h"
|
|
#include "base/strings/string_piece.h"
|
|
#include "net/base/io_buffer.h"
|
|
#include "net/base/ip_address.h"
|
|
#include "net/base/net_export.h"
|
|
#include "net/dns/public/dns_protocol.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
#include "third_party/boringssl/src/include/openssl/sha.h"
|
|
|
|
namespace net {
|
|
|
|
class DnsRecordParser;
|
|
|
|
// Parsed represenation of the extra data in a record. Does not include standard
|
|
// DNS record data such as TTL, Name, Type and Class.
|
|
class NET_EXPORT RecordRdata {
|
|
public:
|
|
virtual ~RecordRdata() = default;
|
|
|
|
// Return true if `data` represents RDATA in the wire format with a valid size
|
|
// for the give `type`. Always returns true for unrecognized `type`s as the
|
|
// size is never known to be invalid.
|
|
static bool HasValidSize(const base::StringPiece& data, uint16_t type);
|
|
|
|
virtual bool IsEqual(const RecordRdata* other) const = 0;
|
|
virtual uint16_t Type() const = 0;
|
|
};
|
|
|
|
// SRV record format (http://www.ietf.org/rfc/rfc2782.txt):
|
|
// 2 bytes network-order unsigned priority
|
|
// 2 bytes network-order unsigned weight
|
|
// 2 bytes network-order unsigned port
|
|
// target: domain name (on-the-wire representation)
|
|
class NET_EXPORT_PRIVATE SrvRecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeSRV;
|
|
|
|
SrvRecordRdata(const SrvRecordRdata&) = delete;
|
|
SrvRecordRdata& operator=(const SrvRecordRdata&) = delete;
|
|
|
|
~SrvRecordRdata() override;
|
|
static std::unique_ptr<SrvRecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
uint16_t priority() const { return priority_; }
|
|
uint16_t weight() const { return weight_; }
|
|
uint16_t port() const { return port_; }
|
|
|
|
const std::string& target() const { return target_; }
|
|
|
|
private:
|
|
SrvRecordRdata();
|
|
|
|
uint16_t priority_ = 0;
|
|
uint16_t weight_ = 0;
|
|
uint16_t port_ = 0;
|
|
|
|
std::string target_;
|
|
};
|
|
|
|
// A Record format (http://www.ietf.org/rfc/rfc1035.txt):
|
|
// 4 bytes for IP address.
|
|
class NET_EXPORT ARecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeA;
|
|
|
|
ARecordRdata(const ARecordRdata&) = delete;
|
|
ARecordRdata& operator=(const ARecordRdata&) = delete;
|
|
|
|
~ARecordRdata() override;
|
|
static std::unique_ptr<ARecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
const IPAddress& address() const { return address_; }
|
|
|
|
private:
|
|
ARecordRdata();
|
|
|
|
IPAddress address_;
|
|
};
|
|
|
|
// AAAA Record format (http://www.ietf.org/rfc/rfc1035.txt):
|
|
// 16 bytes for IP address.
|
|
class NET_EXPORT AAAARecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeAAAA;
|
|
|
|
AAAARecordRdata(const AAAARecordRdata&) = delete;
|
|
AAAARecordRdata& operator=(const AAAARecordRdata&) = delete;
|
|
|
|
~AAAARecordRdata() override;
|
|
static std::unique_ptr<AAAARecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
const IPAddress& address() const { return address_; }
|
|
|
|
private:
|
|
AAAARecordRdata();
|
|
|
|
IPAddress address_;
|
|
};
|
|
|
|
// CNAME record format (http://www.ietf.org/rfc/rfc1035.txt):
|
|
// cname: On the wire representation of domain name.
|
|
class NET_EXPORT_PRIVATE CnameRecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeCNAME;
|
|
|
|
CnameRecordRdata(const CnameRecordRdata&) = delete;
|
|
CnameRecordRdata& operator=(const CnameRecordRdata&) = delete;
|
|
|
|
~CnameRecordRdata() override;
|
|
static std::unique_ptr<CnameRecordRdata> Create(
|
|
const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
const std::string& cname() const { return cname_; }
|
|
|
|
private:
|
|
CnameRecordRdata();
|
|
|
|
std::string cname_;
|
|
};
|
|
|
|
// PTR record format (http://www.ietf.org/rfc/rfc1035.txt):
|
|
// domain: On the wire representation of domain name.
|
|
class NET_EXPORT_PRIVATE PtrRecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypePTR;
|
|
|
|
PtrRecordRdata(const PtrRecordRdata&) = delete;
|
|
PtrRecordRdata& operator=(const PtrRecordRdata&) = delete;
|
|
|
|
~PtrRecordRdata() override;
|
|
static std::unique_ptr<PtrRecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
std::string ptrdomain() const { return ptrdomain_; }
|
|
|
|
private:
|
|
PtrRecordRdata();
|
|
|
|
std::string ptrdomain_;
|
|
};
|
|
|
|
// TXT record format (http://www.ietf.org/rfc/rfc1035.txt):
|
|
// texts: One or more <character-string>s.
|
|
// a <character-string> is a length octet followed by as many characters.
|
|
class NET_EXPORT_PRIVATE TxtRecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeTXT;
|
|
|
|
TxtRecordRdata(const TxtRecordRdata&) = delete;
|
|
TxtRecordRdata& operator=(const TxtRecordRdata&) = delete;
|
|
|
|
~TxtRecordRdata() override;
|
|
static std::unique_ptr<TxtRecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
const std::vector<std::string>& texts() const { return texts_; }
|
|
|
|
private:
|
|
TxtRecordRdata();
|
|
|
|
std::vector<std::string> texts_;
|
|
};
|
|
|
|
// Only the subset of the NSEC record format required by mDNS is supported.
|
|
// Nsec record format is described in http://www.ietf.org/rfc/rfc3845.txt and
|
|
// the limited version required for mDNS described in
|
|
// http://www.rfc-editor.org/rfc/rfc6762.txt Section 6.1.
|
|
class NET_EXPORT_PRIVATE NsecRecordRdata : public RecordRdata {
|
|
public:
|
|
static const uint16_t kType = dns_protocol::kTypeNSEC;
|
|
|
|
NsecRecordRdata(const NsecRecordRdata&) = delete;
|
|
NsecRecordRdata& operator=(const NsecRecordRdata&) = delete;
|
|
|
|
~NsecRecordRdata() override;
|
|
static std::unique_ptr<NsecRecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
// Length of the bitmap in bits.
|
|
// This will be between 8 and 256, per RFC 3845, Section 2.1.2.
|
|
uint16_t bitmap_length() const {
|
|
DCHECK_LE(bitmap_.size(), 32u);
|
|
return static_cast<uint16_t>(bitmap_.size() * 8);
|
|
}
|
|
|
|
// Returns bit i-th bit in the bitmap, where bits withing a byte are organized
|
|
// most to least significant. If it is set, a record with rrtype i exists for
|
|
// the domain name of this nsec record.
|
|
bool GetBit(unsigned i) const;
|
|
|
|
private:
|
|
NsecRecordRdata();
|
|
|
|
std::vector<uint8_t> bitmap_;
|
|
};
|
|
|
|
// OPT record format (https://tools.ietf.org/html/rfc6891):
|
|
class NET_EXPORT_PRIVATE OptRecordRdata : public RecordRdata {
|
|
public:
|
|
class NET_EXPORT_PRIVATE Opt {
|
|
public:
|
|
static constexpr size_t kHeaderSize = 4; // sizeof(code) + sizeof(size)
|
|
|
|
Opt(uint16_t code, base::StringPiece data);
|
|
|
|
bool operator==(const Opt& other) const;
|
|
|
|
uint16_t code() const { return code_; }
|
|
base::StringPiece data() const { return data_; }
|
|
|
|
private:
|
|
uint16_t code_;
|
|
std::string data_;
|
|
};
|
|
|
|
static const uint16_t kType = dns_protocol::kTypeOPT;
|
|
|
|
OptRecordRdata();
|
|
|
|
OptRecordRdata(const OptRecordRdata&) = delete;
|
|
OptRecordRdata& operator=(const OptRecordRdata&) = delete;
|
|
|
|
OptRecordRdata(OptRecordRdata&& other);
|
|
|
|
~OptRecordRdata() override;
|
|
|
|
OptRecordRdata& operator=(OptRecordRdata&& other);
|
|
|
|
static std::unique_ptr<OptRecordRdata> Create(const base::StringPiece& data,
|
|
const DnsRecordParser& parser);
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
const std::vector<char>& buf() const { return buf_; }
|
|
const std::multimap<uint16_t, Opt>& opts() { return opts_; }
|
|
|
|
void AddOpt(const Opt& opt);
|
|
|
|
// Add all Opts from |other| to |this|.
|
|
void AddOpts(const OptRecordRdata& other);
|
|
|
|
// Checks if an Opt with the specified opt_code is in opts_.
|
|
bool ContainsOptCode(uint16_t opt_code) const;
|
|
|
|
private:
|
|
// Opt objects are stored in a multimap; key is the opt code.
|
|
std::multimap<uint16_t, Opt> opts_;
|
|
std::vector<char> buf_;
|
|
};
|
|
|
|
// This class parses and serializes the INTEGRITY DNS record.
|
|
//
|
|
// This RR was invented for a preliminary HTTPSSVC experiment. See the public
|
|
// design doc:
|
|
// https://docs.google.com/document/d/14eCqVyT_3MSj7ydqNFl1Yl0yg1fs6g24qmYUUdi5V-k/edit?usp=sharing
|
|
//
|
|
// The wire format of INTEGRITY records consists of a U16-prefixed nonce
|
|
// followed by |kDigestLen| bytes, which should be equal to the SHA256 hash of
|
|
// the nonce contents.
|
|
class NET_EXPORT IntegrityRecordRdata : public RecordRdata {
|
|
public:
|
|
static constexpr uint16_t kType = dns_protocol::kExperimentalTypeIntegrity;
|
|
|
|
static constexpr size_t kDigestLen = SHA256_DIGEST_LENGTH;
|
|
|
|
using Nonce = std::vector<uint8_t>;
|
|
using Digest = std::array<uint8_t, kDigestLen>;
|
|
|
|
IntegrityRecordRdata() = delete;
|
|
// Constructs a new record, computing the digest value from |nonce|.
|
|
explicit IntegrityRecordRdata(Nonce nonce);
|
|
IntegrityRecordRdata(IntegrityRecordRdata&&);
|
|
IntegrityRecordRdata(const IntegrityRecordRdata&);
|
|
~IntegrityRecordRdata() override;
|
|
|
|
IntegrityRecordRdata& operator=(const IntegrityRecordRdata&) = default;
|
|
IntegrityRecordRdata& operator=(IntegrityRecordRdata&&) = default;
|
|
|
|
// RecordRdata:
|
|
bool IsEqual(const RecordRdata* other) const override;
|
|
uint16_t Type() const override;
|
|
|
|
// Attempts to parse an INTEGRITY record from |data|. Never returns nullptr.
|
|
// The caller can check the intactness of the record with |IsIntact()|.
|
|
static std::unique_ptr<IntegrityRecordRdata> Create(
|
|
const base::StringPiece& data);
|
|
|
|
// Generate an integrity record with a random nonce and corresponding digest.
|
|
// Postcondition: |IsIntact()| is true.
|
|
static IntegrityRecordRdata Random();
|
|
|
|
// Serialize |this| using the INTEGRITY wire format. Returns |absl::nullopt|
|
|
// when |!IsIntact()|.
|
|
absl::optional<std::vector<uint8_t>> Serialize() const;
|
|
|
|
// Precondition: |IsIntact()|.
|
|
const Nonce& nonce() const {
|
|
CHECK(is_intact_);
|
|
return nonce_;
|
|
}
|
|
|
|
// Precondition: |IsIntact()|.
|
|
const Digest& digest() const {
|
|
CHECK(is_intact_);
|
|
return digest_;
|
|
}
|
|
|
|
// To be considered intact, this record must have parsed successfully (if
|
|
// parsed by |Create()|) and the digest must match the hash of the nonce.
|
|
bool IsIntact() const { return is_intact_; }
|
|
|
|
private:
|
|
IntegrityRecordRdata(Nonce nonce_, Digest digest_, size_t rdata_len);
|
|
|
|
static Digest Hash(const Nonce& nonce);
|
|
|
|
// Returns the exact number of bytes a record constructed from |nonce| would
|
|
// occupy when serialized.
|
|
static size_t LengthForSerialization(const Nonce& nonce);
|
|
|
|
Nonce nonce_;
|
|
Digest digest_;
|
|
bool is_intact_;
|
|
};
|
|
|
|
} // namespace net
|
|
|
|
#endif // NET_DNS_RECORD_RDATA_H_
|