diff --git a/crates/proto/src/rr/rdata/svcb.rs b/crates/proto/src/rr/rdata/svcb.rs index cb53aef9..80f6a02e 100644 --- a/crates/proto/src/rr/rdata/svcb.rs +++ b/crates/proto/src/rr/rdata/svcb.rs @@ -5,7 +5,7 @@ // https://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -//! SVCB records, see [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03) +//! SVCB records, see [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460) #![allow(clippy::use_self)] use std::{ @@ -30,7 +30,7 @@ use crate::{ }, }; -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.2) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.2) /// /// ```text /// 2.2. RDATA wire format @@ -51,10 +51,9 @@ use crate::{ /// * a 2 octet field containing the SvcParamKey as an integer in /// network byte order. (See Section 14.3.2 for the defined values.) /// * a 2 octet field containing the length of the SvcParamValue as an -/// integer between 0 and 65535 in network byte order (but constrained -/// by the RDATA and DNS message sizes). -/// * an octet string of this length whose contents are in a format -/// determined by the SvcParamKey. +/// integer between 0 and 65535 in network byte order +/// * an octet string of this length whose contents are the SvcParamValue +/// in a format determined by the SvcParamKey /// /// SvcParamKeys SHALL appear in increasing numeric order. /// @@ -95,7 +94,7 @@ impl SVCB { } } - /// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.4.1) + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.4.1) /// ```text /// 2.4.1. SvcPriority /// @@ -107,9 +106,9 @@ impl SVCB { /// ServiceMode records in the set. /// /// RRSets are explicitly unordered collections, so the SvcPriority field - /// is used to impose an ordering on SVCB RRs. SVCB RRs with a smaller - /// SvcPriority value SHOULD be given preference over RRs with a larger - /// SvcPriority value. + /// is used to impose an ordering on SVCB RRs. A smaller SvcPriority indicates + /// that the domain owner recommends the use of this record over ServiceMode + /// RRs with a larger SvcPriority value. /// /// When receiving an RRSet containing multiple SVCB records with the /// same SvcPriority value, clients SHOULD apply a random shuffle within @@ -120,7 +119,7 @@ impl SVCB { self.svc_priority } - /// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.5) + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.5) /// ```text /// 2.5. Special handling of "." in TargetName /// @@ -138,13 +137,14 @@ impl SVCB { /// /// For ServiceMode SVCB RRs, if TargetName has the value ".", then the /// owner name of this record MUST be used as the effective TargetName. + /// If the record has a wildcard owner name in the zone file, the recipient + /// SHALL use the response's synthesized owner name as the effective TargetName. /// - /// For example, in the following example "svc2.example.net" is the - /// effective TargetName: + /// Here, for example, "svc2.example.net" is the effective TargetName: /// /// example.com. 7200 IN HTTPS 0 svc.example.net. /// svc.example.net. 7200 IN CNAME svc2.example.net. - /// svc2.example.net. 7200 IN HTTPS 1 . port=8002 echconfig="..." + /// svc2.example.net. 7200 IN HTTPS 1 . port=8002 /// svc2.example.net. 300 IN A 192.0.2.2 /// svc2.example.net. 300 IN AAAA 2001:db8::2 /// ``` @@ -158,6 +158,8 @@ impl SVCB { } } +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2) +/// /// ```text /// 14.3.2. Initial contents /// @@ -182,16 +184,16 @@ impl SVCB { /// | 4 | ipv4hint | IPv4 address hints | (This | /// | | | | document) | /// +-------------+-----------------+----------------------+-----------+ -/// | 5 | echconfig | Encrypted | (This | -/// | | | ClientHello info | document) | +/// | 5 | ech | RESERVED (held for | N/A | +/// | | | ECH) | | /// +-------------+-----------------+----------------------+-----------+ /// | 6 | ipv6hint | IPv6 address hints | (This | /// | | | | document) | /// +-------------+-----------------+----------------------+-----------+ -/// | 65280-65534 | keyNNNNN | Private Use | (This | +/// | 65280-65534 | N/A | Private Use | (This | /// | | | | document) | /// +-------------+-----------------+----------------------+-----------+ -/// | 65535 | key65535 | Reserved ("Invalid | (This | +/// | 65535 | N/A | Reserved ("Invalid | (This | /// | | | key") | document) | /// +-------------+-----------------+----------------------+-----------+ /// @@ -360,24 +362,30 @@ pub enum SvcParamValue { /// /// see `Mandatory` Mandatory(Mandatory), - /// The "alpn" and "no-default-alpn" SvcParamKeys together indicate the + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1) + /// + /// ```text + /// The "alpn" and "no-default-alpn" SvcParamKeys together indicate the /// set of Application Layer Protocol Negotiation (ALPN) protocol /// identifiers [Alpn] and associated transport protocols supported by - /// this service endpoint. + /// this service endpoint (the "SVCB ALPN set"). + /// ``` Alpn(Alpn), /// For "no-default-alpn", the presentation and wire format values MUST /// be empty. /// See also `Alpn` NoDefaultAlpn, + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.2) + /// /// ```text - /// 6.2. "port" + /// 7.2. "port" /// /// The "port" SvcParamKey defines the TCP or UDP port that should be /// used to reach this alternative endpoint. If this key is not present, /// clients SHALL use the authority endpoint's port number. /// - /// The presentation "value" of the SvcParamValue is a single decimal - /// integer between 0 and 65535 in ASCII. Any other "value" (e.g. an + /// The presentation value of the SvcParamValue is a single decimal + /// integer between 0 and 65535 in ASCII. Any other value (e.g. an /// empty value) is a syntax error. To enable simpler parsing, this /// SvcParam MUST NOT contain escape sequences. /// @@ -390,6 +398,8 @@ pub enum SvcParamValue { /// caution when using this SvcParamKey to specify a non-default port. /// ``` Port(u16), + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.2) + /// /// The "ipv4hint" and "ipv6hint" keys convey IP addresses that clients /// MAY use to reach the service. If A and AAAA records for TargetName /// are locally available, the client SHOULD ignore these hints. @@ -403,25 +413,15 @@ pub enum SvcParamValue { /// /// see `IpHint` Ipv4Hint(IpHint), + /// [draft-ietf-tls-svcb-ech-01 Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings, Sep 2024](https://datatracker.ietf.org/doc/html/draft-ietf-tls-svcb-ech-01) + /// /// ```text - /// 6.3. "echconfig" + /// 2. "SvcParam for ECH configuration" /// - /// The SvcParamKey to enable Encrypted ClientHello (ECH) is "echconfig". - /// Its value is defined in Section 9. It is applicable to most TLS- - /// based protocols. - /// - /// When publishing a record containing an "echconfig" parameter, the - /// publisher MUST ensure that all IP addresses of TargetName correspond - /// to servers that have access to the corresponding private key or are - /// authoritative for the public name. (See Section 7.2.2 of [ECH] for - /// more details about the public name.) This yields an anonymity set of - /// cardinality equal to the number of ECH-enabled server domains - /// supported by a given client-facing server. Thus, even with an - /// encrypted ClientHello, an attacker who can enumerate the set of ECH- - /// enabled domains supported by a client-facing server can guess the - /// correct SNI with probability at least 1/K, where K is the size of - /// this ECH-enabled server anonymity set. This probability may be - /// increased via traffic analysis or other mechanisms. + /// The "ech" SvcParamKey is defined for conveying the ECH configuration + /// of an alternative endpoint. It is applicable to all TLS-based protocols + /// (including DTLS [RFC9147] and QUIC version 1 [RFC9001]) unless otherwise + /// specified. /// ``` EchConfig(EchConfig), /// See `IpHint` @@ -527,8 +527,10 @@ impl fmt::Display for SvcParamValue { } } +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-8) +/// /// ```text -/// 7. ServiceMode RR compatibility and mandatory keys +/// 8. ServiceMode RR compatibility and mandatory keys /// /// In a ServiceMode RR, a SvcParamKey is considered "mandatory" if the /// RR will not function correctly for clients that ignore this @@ -540,11 +542,10 @@ impl fmt::Display for SvcParamValue { /// /// A ServiceMode RR is considered "compatible" with a client if the /// client recognizes all the mandatory keys, and their values indicate -/// that successful connection establishment is possible. If the SVCB -/// RRSet contains no compatible RRs, the client will generally act as if -/// the RRSet is empty. +/// that successful connection establishment is possible. Incompatible RRs +/// are ignored (see step 5 of the procedure defined in Section 3) /// -/// The presentation "value" SHALL be a comma-separated list +/// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more valid SvcParamKeys, either by their /// registered name or in the unknown-key format (Section 2.1). Keys MAY /// appear in any order, but MUST NOT appear more than once. For self- @@ -556,10 +557,10 @@ impl fmt::Display for SvcParamValue { /// /// For example, the following is a valid list of SvcParams: /// -/// echconfig=... key65333=ex1 key65444=ex2 mandatory=key65444,echconfig +/// ipv6hint=... key65333=ex1 key65444=ex2 mandatory=key65444,ipv6hint /// /// In wire format, the keys are represented by their numeric values in -/// network byte order, concatenated in ascending order. +/// network byte order, concatenated in strictly increasing numeric order. /// /// This SvcParamKey is always automatically mandatory, and MUST NOT /// appear in its own value-list. Other automatically mandatory keys @@ -577,7 +578,7 @@ impl<'r> BinDecodable<'r> for Mandatory { /// /// ```text /// In wire format, the keys are represented by their numeric values in - /// network byte order, concatenated in ascending order. + /// network byte order, concatenated in strictly increasing numeric order. /// ``` fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult { let mut keys = Vec::with_capacity(1); @@ -600,7 +601,7 @@ impl BinEncodable for Mandatory { /// /// ```text /// In wire format, the keys are represented by their numeric values in - /// network byte order, concatenated in ascending order. + /// network byte order, concatenated in strictly increasing numeric order. /// ``` fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> { if self.0.is_empty() { @@ -617,7 +618,9 @@ impl BinEncodable for Mandatory { } impl fmt::Display for Mandatory { - /// The presentation "value" SHALL be a comma-separated list + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-8) + /// + /// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more valid SvcParamKeys, either by their /// registered name or in the unknown-key format (Section 2.1). Keys MAY /// appear in any order, but MUST NOT appear more than once. For self- @@ -629,7 +632,7 @@ impl fmt::Display for Mandatory { /// /// For example, the following is a valid list of SvcParams: /// - /// echconfig=... key65333=ex1 key65444=ex2 mandatory=key65444,echconfig + /// ipv6hint=... key65333=ex1 key65444=ex2 mandatory=key65444,ipv6hint fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { for key in self.0.iter() { // TODO: confirm in the RFC that trailing commas are ok @@ -640,7 +643,7 @@ impl fmt::Display for Mandatory { } } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-6.1) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1) /// /// ```text /// 6.1. "alpn" and "no-default-alpn" @@ -652,18 +655,29 @@ impl fmt::Display for Mandatory { /// /// As with Alt-Svc [AltSvc], the ALPN protocol identifier is used to /// identify the application protocol and associated suite of protocols -/// supported by the endpoint (the "protocol suite"). Clients filter the -/// set of ALPN identifiers to match the protocol suites they support, -/// and this informs the underlying transport protocol used (such as -/// QUIC-over-UDP or TLS-over-TCP). +/// supported by the endpoint (the "protocol suite"). The presence of an +/// ALPN protocol identifier in the SVCB ALPN set indicates that this +/// service endpoint, described by TargetName and the other parameters +/// (e.g., "port"), offers service with the protocol suite associated +/// with this ALPN identifier. +/// +/// Clients filter the set of ALPN identifiers to match the protocol suites +/// they support, and this informs the underlying transport protocol used +/// (such as QUIC over UDP or TLS over TCP). ALPN protocol identifiers that do +/// not uniquely identify a protocol suite (e.g., an Identification Sequence +/// that can be used with both TLS and DTLS) are not compatible with this +/// SvcParamKey and MUST NOT be included in the SVCB ALPN set. /// /// ALPNs are identified by their registered "Identification Sequence" /// ("alpn-id"), which is a sequence of 1-255 octets. /// /// alpn-id = 1*255OCTET /// -/// The presentation "value" SHALL be a comma-separated list -/// (Appendix A.1) of one or more "alpn-id"s. +/// For "alpn", the presentation value SHALL be a comma-separated list +/// (Appendix A.1) of one or more alpn-ids. Zone-file implementations MAY +/// disallow the "," and "\" characters in ALPN IDs instead of implementing +/// the value-list escaping procedure, relying on the opaque key format +/// (e.g., key1=\002h2) in the event that these characters are needed. /// /// The wire format value for "alpn" consists of at least one "alpn-id" /// prefixed by its length as a single octet, and these length-value @@ -676,19 +690,11 @@ impl fmt::Display for Mandatory { /// also be specified in order for the RR to be "self-consistent" /// (Section 2.4.3). /// -/// Each scheme that uses this SvcParamKey defines a "default set" of -/// supported ALPNs, which SHOULD NOT be empty. To determine the set of -/// protocol suites supported by an endpoint (the "SVCB ALPN set"), the -/// client adds the default set to the list of "alpn-id"s unless the "no- -/// default-alpn" SvcParamKey is present. The presence of an ALPN -/// protocol in the SVCB ALPN set indicates that this service endpoint, -/// described by TargetName and the other parameters (e.g. "port") offers -/// service with the protocol suite associated with this ALPN protocol. -/// -/// ALPN protocol names that do not uniquely identify a protocol suite -/// (e.g. an Identification Sequence that can be used with both TLS and -/// DTLS) are not compatible with this SvcParamKey and MUST NOT be -/// included in the SVCB ALPN set. +/// Each scheme that uses this SvcParamKey defines a "default set" of ALPN +/// IDs that are supported by nearly all clients and servers; this set MAY +/// be empty. To determine the SVCB ALPN set, the client starts with the +/// list of alpn-ids from the "alpn" SvcParamKey, and it adds the default +/// set unless the "no-default-alpn" SvcParamKey is present. /// /// To establish a connection to the endpoint, clients MUST /// @@ -713,6 +719,12 @@ impl fmt::Display for Mandatory { /// in that handshake proceeds as specified in [ALPN], without regard to /// the SVCB ALPN set. /// +/// Clients MAY implement a fallback procedure, using a less-preferred +/// transport if more-preferred transports fail to connect. This fallback +/// behavior is vulnerable to manipulation by a network attacker who blocks +/// the more-preferred transports, but it may be necessary for compatibility +/// with existing networks. +/// /// With this procedure in place, an attacker who can modify DNS and /// network traffic can prevent a successful transport connection, but /// cannot otherwise interfere with ALPN protocol selection. This @@ -720,15 +732,16 @@ impl fmt::Display for Mandatory { /// one protocol from the SVCB ALPN set. /// /// Clients SHOULD NOT attempt connection to a service endpoint whose -/// SVCB ALPN set does not contain any supported protocols. To ensure -/// consistency of behavior, clients MAY reject the entire SVCB RRSet and -/// fall back to basic connection establishment if all of the RRs +/// SVCB ALPN set does not contain any supported protocols. +/// +/// To ensure consistency of behavior, clients MAY reject the entire SVCB RRSet +/// and fall back to basic connection establishment if all of the RRs /// indicate "no-default-alpn", even if connection could have succeeded /// using a non-default alpn. /// -/// For compatibility with clients that require default transports, zone -/// operators SHOULD ensure that at least one RR in each RRSet supports -/// the default transports. +/// Zone operators SHOULD ensure that at least one RR in each RRset supports +/// the default transports. This enables compatibility with the greatest +/// number of clients. /// ``` #[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))] #[derive(Debug, PartialEq, Eq, Hash, Clone)] @@ -783,7 +796,7 @@ impl BinEncodable for Alpn { } impl fmt::Display for Alpn { - /// The presentation "value" SHALL be a comma-separated list + /// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more "alpn-id"s. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { for alpn in self.0.iter() { @@ -795,26 +808,15 @@ impl fmt::Display for Alpn { } } +/// [draft-ietf-tls-svcb-ech-01 Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings, Sep 2024](https://datatracker.ietf.org/doc/html/draft-ietf-tls-svcb-ech-01) +/// /// ```text -/// 9. SVCB/HTTPS RR parameter for ECH configuration +/// 2. "SvcParam for ECH configuration" /// -/// The SVCB "echconfig" parameter is defined for conveying the ECH -/// configuration of an alternative endpoint. In wire format, the value -/// of the parameter is an ECHConfigs vector [ECH], including the -/// redundant length prefix. In presentation format, the value is a -/// single ECHConfigs encoded in Base64 [base64]. Base64 is used here to -/// simplify integration with TLS server software. To enable simpler -/// parsing, this SvcParam MUST NOT contain escape sequences. -/// -/// When ECH is in use, the TLS ClientHello is divided into an -/// unencrypted "outer" and an encrypted "inner" ClientHello. The outer -/// ClientHello is an implementation detail of ECH, and its contents are -/// controlled by the ECHConfig in accordance with [ECH]. The inner -/// ClientHello is used for establishing a connection to the service, so -/// its contents may be influenced by other SVCB parameters. For -/// example, the requirements on the ProtocolNameList in Section 6.1 -/// apply only to the inner ClientHello. Similarly, it is the inner -/// ClientHello whose Server Name Indication identifies the desired +/// The "ech" SvcParamKey is defined for conveying the ECH configuration +/// of an alternative endpoint. It is applicable to all TLS-based protocols +/// (including DTLS [RFC9147] and QUIC version 1 [RFC9001]) unless +/// otherwise specified. /// ``` #[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))] #[derive(PartialEq, Eq, Hash, Clone)] @@ -822,10 +824,11 @@ impl fmt::Display for Alpn { pub struct EchConfig(pub Vec); impl<'r> BinDecodable<'r> for EchConfig { - /// In wire format, the value - /// of the parameter is an ECHConfigs vector (ECH), including the - /// redundant length prefix (a 2 octet field containing the length of the SvcParamValue - /// as an integer between 0 and 65535 in network byte order). + /// In wire format, the value of the parameter is an ECHConfigList (Section 4 of draft-ietf-tls-esni-18), + /// including the redundant length prefix. In presentation format, the value is the + /// ECHConfigList in Base 64 Encoding (Section 4 of RFC4648). + /// Base 64 is used here to simplify integration with TLS server software. + /// To enable simpler parsing, this SvcParam MUST NOT contain escape sequences. fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult { let redundant_len = decoder .read_u16()? @@ -841,10 +844,11 @@ impl<'r> BinDecodable<'r> for EchConfig { } impl BinEncodable for EchConfig { - /// In wire format, the value - /// of the parameter is an ECHConfigs vector (ECH), including the - /// redundant length prefix (a 2 octet field containing the length of the SvcParamValue - /// as an integer between 0 and 65535 in network byte order). + /// In wire format, the value of the parameter is an ECHConfigList (Section 4 of draft-ietf-tls-esni-18), + /// including the redundant length prefix. In presentation format, the value is the + /// ECHConfigList in Base 64 Encoding (Section 4 of RFC4648). + /// Base 64 is used here to simplify integration with TLS server software. + /// To enable simpler parsing, this SvcParam MUST NOT contain escape sequences. fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> { let len = u16::try_from(self.0.len()) .map_err(|_| ProtoError::from("ECH value length exceeds max size of u16::MAX"))?; @@ -861,12 +865,12 @@ impl fmt::Display for EchConfig { /// As the documentation states, the presentation format (what this function outputs) must be a BASE64 encoded string. /// hickory-dns will encode to BASE64 during formatting of the internal data, and output the BASE64 value. /// - /// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-9) + /// [draft-ietf-tls-svcb-ech-01 Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings, Sep 2024](https://datatracker.ietf.org/doc/html/draft-ietf-tls-svcb-ech-01) /// ```text - /// In presentation format, the value is a - /// single ECHConfigs encoded in Base64 [base64]. Base64 is used here to - /// simplify integration with TLS server software. To enable simpler - /// parsing, this SvcParam MUST NOT contain escape sequences. + /// In presentation format, the value is the ECHConfigList in Base 64 Encoding + /// (Section 4 of [RFC4648]). Base 64 is used here to simplify integration with + /// TLS server software. To enable simpler parsing, this SvcParam MUST NOT + /// contain escape sequences. /// ``` /// /// *note* while the on the wire the EchConfig has a redundant length, @@ -888,8 +892,10 @@ impl fmt::Debug for EchConfig { } } +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.3) +/// /// ```text -/// 6.4. "ipv4hint" and "ipv6hint" +/// 7.3. "ipv4hint" and "ipv6hint" /// /// The "ipv4hint" and "ipv6hint" keys convey IP addresses that clients /// MAY use to reach the service. If A and AAAA records for TargetName @@ -902,24 +908,24 @@ impl fmt::Debug for EchConfig { /// and/or AAAA response addresses could negatively impact load balancing /// or other geo-aware features and thereby degrade client performance. /// -/// The presentation "value" SHALL be a comma-separated list +/// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more IP addresses of the appropriate family /// in standard textual format [RFC5952]. To enable simpler parsing, /// this SvcParamValue MUST NOT contain escape sequences. /// /// The wire format for each parameter is a sequence of IP addresses in -/// network byte order. Like an A or AAAA RRSet, the list of addresses -/// represents an unordered collection, and clients SHOULD pick addresses -/// to use in a random order. An empty list of addresses is invalid. +/// network byte order (for the respective address family). Like an A or +/// AAAA RRSet, the list of addresses represents an unordered collection, +/// and clients SHOULD pick addresses to use in a random order. An empty +/// list of addresses is invalid. /// /// When selecting between IPv4 and IPv6 addresses to use, clients may /// use an approach such as Happy Eyeballs [HappyEyeballsV2]. When only -/// "ipv4hint" is present, IPv6-only clients may synthesize IPv6 -/// addresses as specified in [RFC7050] or ignore the "ipv4hint" key and -/// wait for AAAA resolution (Section 3). Recursive resolvers MUST NOT -/// perform DNS64 ([RFC6147]) on parameters within a SVCB record. For -/// best performance, server operators SHOULD include an "ipv6hint" -/// parameter whenever they include an "ipv4hint" parameter. +/// "ipv4hint" is present, NAT64 clients may synthesize IPv6 addresses +/// as specified in [RFC7050] or ignore the "ipv4hint" key and +/// wait for AAAA resolution (Section 3). For best performance, server +/// operators SHOULD include an "ipv6hint" parameter whenever they +/// include an "ipv4hint" parameter. /// /// These parameters are intended to minimize additional connection /// latency when a recursive resolver is not compliant with the @@ -939,9 +945,10 @@ where T: BinDecodable<'r>, { /// The wire format for each parameter is a sequence of IP addresses in - /// network byte order. Like an A or AAAA RRSet, the list of addresses - /// represents an unordered collection, and clients SHOULD pick addresses - /// to use in a random order. An empty list of addresses is invalid. + /// network byte order (for the respective address family). Like an A or + /// AAAA RRSet, the list of addresses represents an unordered collection, + /// and clients SHOULD pick addresses to use in a random order. An empty + /// list of addresses is invalid. fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult { let mut ips = Vec::new(); @@ -958,9 +965,10 @@ where T: BinEncodable, { /// The wire format for each parameter is a sequence of IP addresses in - /// network byte order. Like an A or AAAA RRSet, the list of addresses - /// represents an unordered collection, and clients SHOULD pick addresses - /// to use in a random order. An empty list of addresses is invalid. + /// network byte order (for the respective address family). Like an A or + /// AAAA RRSet, the list of addresses represents an unordered collection, + /// and clients SHOULD pick addresses to use in a random order. An empty + /// list of addresses is invalid. fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> { for ip in self.0.iter() { ip.emit(encoder)?; @@ -974,7 +982,7 @@ impl fmt::Display for IpHint where T: fmt::Display, { - /// The presentation "value" SHALL be a comma-separated list + /// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more IP addresses of the appropriate family /// in standard textual format [RFC 5952](https://tools.ietf.org/html/rfc5952). To enable simpler parsing, /// this SvcParamValue MUST NOT contain escape sequences. @@ -987,15 +995,15 @@ where } } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.1) -/// ```text -/// Unrecognized keys are represented in presentation format as -/// "keyNNNNN" where NNNNN is the numeric value of the key type without -/// leading zeros. A SvcParam in this form SHALL be parsed as specified -/// above, and the decoded "value" SHALL be used as its wire format -/// encoding. +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.1) /// -/// For some SvcParamKeys, the "value" corresponds to a list or set of +/// ```text +/// Arbitrary keys can be represented using the unknown-key presentation +/// format "keyNNNNN" where NNNNN is the numeric value of the key type +/// without leading zeros. A SvcParam in this form SHALL be parsed as specified +/// above, and the decoded value SHALL be used as its wire-format encoding. +/// +/// For some SvcParamKeys, the value corresponds to a list or set of /// items. Presentation formats for such keys SHOULD use a comma- /// separated list (Appendix A.1). /// @@ -1066,6 +1074,8 @@ impl BinEncodable for SVCB { impl<'r> RecordDataDecodable<'r> for SVCB { /// Reads the SVCB record from the decoder. /// + /// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.2) + /// /// ```text /// Clients MUST consider an RR malformed if: /// @@ -1150,7 +1160,7 @@ impl RecordData for SVCB { } } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-10.3) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-10.4) /// /// ```text /// simple.example. 7200 IN HTTPS 1 . alpn=h3 diff --git a/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs b/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs index ae9c9129..b6e841f4 100644 --- a/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs +++ b/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs @@ -20,49 +20,50 @@ use crate::{ }, }; -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.2) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.1) /// /// ```text /// 2.1. Zone file presentation format /// -/// The presentation format of the record is: +/// The presentation format of the record ([RFC1035]) has the form: /// -/// Name TTL IN SVCB SvcPriority TargetName SvcParams +/// SvcPriority TargetName SvcParams /// /// The SVCB record is defined specifically within the Internet ("IN") /// Class ([RFC1035]). /// -/// SvcPriority is a number in the range 0-65535, TargetName is a domain -/// name, and the SvcParams are a whitespace-separated list, with each -/// SvcParam consisting of a SvcParamKey=SvcParamValue pair or a -/// standalone SvcParamKey. SvcParamKeys are subject to IANA control -/// (Section 14.3). +/// SvcPriority is a number in the range 0-65535, TargetName is a +/// ([RFC1035], Section 5.1), and the SvcParams are +/// a whitespace-separated list, with each SvcParam consisting of a +/// SvcParamKey=SvcParamValue pair or a standalone SvcParamKey. +/// SvcParamKeys are registered by IANA (Section 14.3). /// /// Each SvcParamKey SHALL appear at most once in the SvcParams. In -/// presentation format, SvcParamKeys are lower-case alphanumeric +/// presentation format, SvcParamKeys are lowercase alphanumeric /// strings. Key names should contain 1-63 characters from the ranges /// "a"-"z", "0"-"9", and "-". In ABNF [RFC5234], /// /// alpha-lc = %x61-7A ; a-z /// SvcParamKey = 1*63(alpha-lc / DIGIT / "-") /// SvcParam = SvcParamKey ["=" SvcParamValue] -/// SvcParamValue = char-string -/// value = *OCTET +/// SvcParamValue = char-string ; See Appendix A. +/// value = *OCTET ; Value before key-specific parsing /// /// The SvcParamValue is parsed using the character-string decoding -/// algorithm (Appendix A), producing a "value". The "value" is then +/// algorithm (Appendix A), producing a value. The value is then /// validated and converted into wire-format in a manner specific to each /// key. /// -/// When the "=" is omitted, the "value" is interpreted as empty. +/// When the optional "=" and SvcParamValue are omitted, the value is +/// interpreted as empty. /// -/// Unrecognized keys are represented in presentation format as -/// "keyNNNNN" where NNNNN is the numeric value of the key type without -/// leading zeros. A SvcParam in this form SHALL be parsed as specified -/// above, and the decoded "value" SHALL be used as its wire format +/// Arbitrary keys can be represented using the unknown-key presentation +/// format "keyNNNNN" where NNNNN is the numeric value of the key type +/// without leading zeros. A SvcParam in this form SHALL be parsed as +/// specified above, and the decoded value SHALL be used as its wire-format /// encoding. /// -/// For some SvcParamKeys, the "value" corresponds to a list or set of +/// For some SvcParamKeys, the value corresponds to a list or set of /// items. Presentation formats for such keys SHOULD use a comma- /// separated list (Appendix A.1). /// @@ -144,9 +145,10 @@ fn parse_char_data(value: &str) -> Result { } } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-7) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-8) +/// /// ```text -/// The presentation "value" SHALL be a comma-separated list +/// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more valid SvcParamKeys, either by their /// registered name or in the unknown-key format (Section 2.1). Keys MAY /// appear in any order, but MUST NOT appear more than once. For self- @@ -158,7 +160,7 @@ fn parse_char_data(value: &str) -> Result { /// /// For example, the following is a valid list of SvcParams: /// -/// echconfig=... key65333=ex1 key65444=ex2 mandatory=key65444,echconfig +/// ipv6hint=... key65333=ex1 key65444=ex2 mandatory=key65444,ipv6hint /// ``` /// /// Currently this does not validate that the mandatory section matches the other keys @@ -173,15 +175,16 @@ fn parse_mandatory(value: Option<&str>) -> Result { Ok(SvcParamValue::Mandatory(Mandatory(mandatories))) } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-6.1) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1.1) +/// /// ```text -/// ALPNs are identified by their registered "Identification Sequence" +/// ALPNs are identified by their registered "Identification Sequence" /// ("alpn-id"), which is a sequence of 1-255 octets. /// /// alpn-id = 1*255OCTET /// -/// The presentation "value" SHALL be a comma-separated list -/// (Appendix A.1) of one or more "alpn-id"s. +/// For "alpn", the presentation value SHALL be a comma-separated list +/// (Appendix A.1) of one or more alpn-ids. /// ``` /// /// This does not currently check to see if the ALPN code is legitimate @@ -194,9 +197,10 @@ fn parse_alpn(value: Option<&str>) -> Result { Ok(SvcParamValue::Alpn(Alpn(alpns))) } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-6.1) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1.1) +/// /// ```text -/// For "no-default-alpn", the presentation and wire format values MUST +/// For "no-default-alpn", the presentation and wire format values MUST /// be empty. When "no-default-alpn" is specified in an RR, "alpn" must /// also be specified in order for the RR to be "self-consistent" /// (Section 2.4.3). @@ -209,10 +213,11 @@ fn parse_no_default_alpn(value: Option<&str>) -> Result) -> Result { Ok(SvcParamValue::Port(port)) } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-6.4) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.3) +/// /// ```text -/// The presentation "value" SHALL be a comma-separated list +/// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more IP addresses of the appropriate family /// in standard textual format [RFC5952]. To enable simpler parsing, /// this SvcParamValue MUST NOT contain escape sequences. @@ -242,15 +248,15 @@ fn parse_ipv4_hint(value: Option<&str>) -> Result { Ok(SvcParamValue::Ipv4Hint(IpHint(hints))) } -/// As the documentation states, the presentation format (what this function reads) must be a BASE64 encoded string. -/// hickory-dns will decode the BASE64 during parsing and stores the internal data as the raw bytes. +/// As the documentation states, the presentation format (what this function outputs) must be a BASE64 encoded string. +/// hickory-dns will encode to BASE64 during formatting of the internal data, and output the BASE64 value. /// -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-9) +/// [draft-ietf-tls-svcb-ech-01 Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings, Sep 2024](https://datatracker.ietf.org/doc/html/draft-ietf-tls-svcb-ech-01) /// ```text -/// In presentation format, the value is a -/// single ECHConfigs encoded in Base64 [base64]. Base64 is used here to -/// simplify integration with TLS server software. To enable simpler -/// parsing, this SvcParam MUST NOT contain escape sequences. +/// In presentation format, the value is the ECHConfigList in Base 64 Encoding +/// (Section 4 of [RFC4648]). Base 64 is used here to simplify integration with +/// TLS server software. To enable simpler parsing, this SvcParam MUST NOT +/// contain escape sequences. /// ``` fn parse_ech_config(value: Option<&str>) -> Result { let value = value.ok_or_else(|| { @@ -264,9 +270,10 @@ fn parse_ech_config(value: Option<&str>) -> Result { Ok(SvcParamValue::EchConfig(EchConfig(ech_config_bytes))) } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-6.4) +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-7.3) +/// /// ```text -/// The presentation "value" SHALL be a comma-separated list +/// The presentation value SHALL be a comma-separated list /// (Appendix A.1) of one or more IP addresses of the appropriate family /// in standard textual format [RFC5952]. To enable simpler parsing, /// this SvcParamValue MUST NOT contain escape sequences. @@ -280,15 +287,15 @@ fn parse_ipv6_hint(value: Option<&str>) -> Result { Ok(SvcParamValue::Ipv6Hint(IpHint(hints))) } -/// [draft-ietf-dnsop-svcb-https-03 SVCB and HTTPS RRs for DNS, February 2021](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2.1) -/// ```text -/// Unrecognized keys are represented in presentation format as -/// "keyNNNNN" where NNNNN is the numeric value of the key type without -/// leading zeros. A SvcParam in this form SHALL be parsed as specified -/// above, and the decoded "value" SHALL be used as its wire format -/// encoding. +/// [RFC 9460 SVCB and HTTPS Resource Records, Nov 2023](https://datatracker.ietf.org/doc/html/rfc9460#section-2.1) /// -/// For some SvcParamKeys, the "value" corresponds to a list or set of +/// ```text +/// Arbitrary keys can be represented using the unknown-key presentation +/// format "keyNNNNN" where NNNNN is the numeric value of the key type +/// without leading zeros. A SvcParam in this form SHALL be parsed as specified +/// above, and the decoded value SHALL be used as its wire-format encoding. +/// +/// For some SvcParamKeys, the value corresponds to a list or set of /// items. Presentation formats for such keys SHOULD use a comma- /// separated list (Appendix A.1). ///