| /* |
| * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com> |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //! signature record for signing queries, updates, and responses |
| |
| use crate::error::*; |
| use crate::rr::dnssec::Algorithm; |
| use crate::rr::{Name, RecordType}; |
| use crate::serialize::binary::*; |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4) |
| /// |
| /// NOTE: RFC 2535 was obsoleted with 4034+, with the exception of the |
| /// usage for UPDATE, which is what this implementation is for. |
| /// |
| /// ```text |
| /// 4.1 SIG RDATA Format |
| /// |
| /// The RDATA portion of a SIG RR is as shown below. The integrity of |
| /// the RDATA information is protected by the signature field. |
| /// |
| /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 |
| /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// | type covered | algorithm | labels | |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// | original TTL | |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// | signature expiration | |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// | signature inception | |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// | key tag | | |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name + |
| /// | / |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/ |
| /// / / |
| /// / signature / |
| /// / / |
| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| /// |
| /// ``` |
| /// [RFC 2931](https://tools.ietf.org/html/rfc2931), DNS Request and Transaction Signatures, September 2000 |
| /// |
| /// NOTE: 2931 updates SIG0 to clarify certain particulars... |
| /// |
| /// ```text |
| /// RFC 2931 DNS SIG(0) September 2000 |
| /// |
| /// 3. The SIG(0) Resource Record |
| /// |
| /// The structure of and type number of SIG resource records (RRs) is |
| /// given in [RFC 2535] Section 4.1. However all of Section 4.1.8.1 and |
| /// the parts of Sections 4.2 and 4.3 related to SIG(0) should be |
| /// considered replaced by the material below. Any conflict between [RFC |
| /// 2535] and this document concerning SIG(0) RRs should be resolved in |
| /// favor of this document. |
| /// |
| /// For all transaction SIG(0)s, the signer field MUST be a name of the |
| /// originating host and there MUST be a KEY RR at that name with the |
| /// public key corresponding to the private key used to calculate the |
| /// signature. (The host domain name used may be the inverse IP address |
| /// mapping name for an IP address of the host if the relevant KEY is |
| /// stored there.) |
| /// |
| /// For all SIG(0) RRs, the owner name, class, TTL, and original TTL, are |
| /// meaningless. The TTL fields SHOULD be zero and the CLASS field |
| /// SHOULD be ANY. To conserve space, the owner name SHOULD be root (a |
| /// single zero octet). When SIG(0) authentication on a response is |
| /// desired, that SIG RR MUST be considered the highest priority of any |
| /// additional information for inclusion in the response. If the SIG(0) |
| /// RR cannot be added without causing the message to be truncated, the |
| /// server MUST alter the response so that a SIG(0) can be included. |
| /// This response consists of only the question and a SIG(0) record, and |
| /// has the TC bit set and RCODE 0 (NOERROR). The client should at this |
| /// point retry the request using TCP. |
| /// |
| /// 3.1 Calculating Request and Transaction SIGs |
| /// |
| /// A DNS request may be optionally signed by including one SIG(0)s at |
| /// the end of the query additional information section. Such a SIG is |
| /// identified by having a "type covered" field of zero. It signs the |
| /// preceding DNS request message including DNS header but not including |
| /// the UDP/IP header and before the request RR counts have been adjusted |
| /// for the inclusions of the request SIG(0). |
| /// |
| /// It is calculated by using a "data" (see [RFC 2535], Section 4.1.8) of |
| /// (1) the SIG's RDATA section entirely omitting (not just zeroing) the |
| /// signature subfield itself, (2) the DNS query messages, including DNS |
| /// header, but not the UDP/IP header and before the reply RR counts have |
| /// been adjusted for the inclusion of the SIG(0). That is |
| /// |
| /// data = RDATA | request - SIG(0) |
| /// |
| /// where "|" is concatenation and RDATA is the RDATA of the SIG(0) being |
| /// calculated less the signature itself. |
| /// |
| /// Similarly, a SIG(0) can be used to secure a response and the request |
| /// that produced it. Such transaction signatures are calculated by |
| /// using a "data" of (1) the SIG's RDATA section omitting the signature |
| /// itself, (2) the entire DNS query message that produced this response, |
| /// including the query's DNS header but not its UDP/IP header, and (3) |
| /// the entire DNS response message, including DNS header but not the |
| /// UDP/IP header and before the response RR counts have been adjusted |
| /// for the inclusion of the SIG(0). |
| /// |
| /// That is |
| /// |
| /// data = RDATA | full query | response - SIG(0) |
| /// |
| /// where "|" is concatenation and RDATA is the RDATA of the SIG(0) being |
| /// calculated less the signature itself. |
| /// |
| /// Verification of a response SIG(0) (which is signed by the server host |
| /// key, not the zone key) by the requesting resolver shows that the |
| /// query and response were not tampered with in transit, that the |
| /// response corresponds to the intended query, and that the response |
| /// comes from the queried server. |
| /// |
| /// In the case of a DNS message via TCP, a SIG(0) on the first data |
| /// packet is calculated with "data" as above and for each subsequent |
| /// packet, it is calculated as follows: |
| /// |
| /// data = RDATA | DNS payload - SIG(0) | previous packet |
| /// |
| /// where "|" is concatenations, RDATA is as above, and previous packet |
| /// is the previous DNS payload including DNS header and the SIG(0) but |
| /// not the TCP/IP header. Support of SIG(0) for TCP is OPTIONAL. As an |
| /// alternative, TSIG may be used after, if necessary, setting up a key |
| /// with TKEY [RFC 2930]. |
| /// |
| /// Except where needed to authenticate an update, TKEY, or similar |
| /// privileged request, servers are not required to check a request |
| /// SIG(0). |
| /// |
| /// Note: requests and responses can either have a single TSIG or one |
| /// SIG(0) but not both a TSIG and a SIG(0). |
| /// |
| /// 3.2 Processing Responses and SIG(0) RRs |
| /// |
| /// If a SIG RR is at the end of the additional information section of a |
| /// response and has a type covered of zero, it is a transaction |
| /// signature covering the response and the query that produced the |
| /// response. For TKEY responses, it MUST be checked and the message |
| /// rejected if the checks fail unless otherwise specified for the TKEY |
| /// mode in use. For all other responses, it MAY be checked and the |
| /// message rejected if the checks fail. |
| /// |
| /// If a response's SIG(0) check succeed, such a transaction |
| /// authentication SIG does NOT directly authenticate the validity any |
| /// data-RRs in the message. However, it authenticates that they were |
| /// sent by the queried server and have not been diddled. (Only a proper |
| /// SIG(0) RR signed by the zone or a key tracing its authority to the |
| /// zone or to static resolver configuration can directly authenticate |
| /// |
| /// data-RRs, depending on resolver policy.) If a resolver or server does |
| /// not implement transaction and/or request SIGs, it MUST ignore them |
| /// without error where they are optional and treat them as failing where |
| /// they are required. |
| /// |
| /// 3.3 SIG(0) Lifetime and Expiration |
| /// |
| /// The inception and expiration times in SIG(0)s are for the purpose of |
| /// resisting replay attacks. They should be set to form a time bracket |
| /// such that messages outside that bracket can be ignored. In IP |
| /// networks, this time bracket should not normally extend further than 5 |
| /// minutes into the past and 5 minutes into the future. |
| /// ``` |
| #[derive(Debug, PartialEq, Eq, Hash, Clone)] |
| pub struct SIG { |
| type_covered: RecordType, |
| algorithm: Algorithm, |
| num_labels: u8, |
| original_ttl: u32, |
| sig_expiration: u32, |
| sig_inception: u32, |
| key_tag: u16, |
| signer_name: Name, |
| sig: Vec<u8>, |
| } |
| |
| impl SIG { |
| /// Creates a new SIG record data, used for both RRSIG and SIG(0) records. |
| /// |
| /// # Arguments |
| /// |
| /// * `type_covered` - The `RecordType` which this signature covers, should be NULL for SIG(0). |
| /// * `algorithm` - The `Algorithm` used to generate the `signature`. |
| /// * `num_labels` - The number of labels in the name, should be less 1 for *.name labels, |
| /// see `Name::num_labels()`. |
| /// * `original_ttl` - The TTL for the RRSet stored in the zone, should be 0 for SIG(0). |
| /// * `sig_expiration` - Timestamp at which this signature is no longer valid, very important to |
| /// keep this low, < +5 minutes to limit replay attacks. |
| /// * `sig_inception` - Timestamp when this signature was generated. |
| /// * `key_tag` - See the key_tag generation in `rr::dnssec::Signer::key_tag()`. |
| /// * `signer_name` - Domain name of the server which was used to generate the signature. |
| /// * `sig` - signature stored in this record. |
| /// |
| /// # Return value |
| /// |
| /// The new SIG record data. |
| #[allow(clippy::too_many_arguments)] |
| pub fn new( |
| type_covered: RecordType, |
| algorithm: Algorithm, |
| num_labels: u8, |
| original_ttl: u32, |
| sig_expiration: u32, |
| sig_inception: u32, |
| key_tag: u16, |
| signer_name: Name, |
| sig: Vec<u8>, |
| ) -> SIG { |
| SIG { |
| type_covered, |
| algorithm, |
| num_labels, |
| original_ttl, |
| sig_expiration, |
| sig_inception, |
| key_tag, |
| signer_name, |
| sig, |
| } |
| } |
| |
| /// Add actual signature value to existing SIG record data. |
| /// |
| /// # Arguments |
| /// |
| /// * `signature` - signature to be stored in this record. |
| /// |
| /// # Return value |
| /// |
| /// The new SIG record data. |
| pub fn set_sig(self, signature: Vec<u8>) -> Self { |
| SIG { |
| type_covered: self.type_covered, |
| algorithm: self.algorithm, |
| num_labels: self.num_labels, |
| original_ttl: self.original_ttl, |
| sig_expiration: self.sig_expiration, |
| sig_inception: self.sig_inception, |
| key_tag: self.key_tag, |
| signer_name: self.signer_name, |
| sig: signature, |
| } |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.1) |
| /// |
| /// ```text |
| /// 4.1.1 Type Covered Field |
| /// |
| /// The "type covered" is the type of the other RRs covered by this SIG. |
| /// ``` |
| pub fn type_covered(&self) -> RecordType { |
| self.type_covered |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.2) |
| /// |
| /// ```text |
| /// 4.1.2 Algorithm Number Field |
| /// |
| /// This octet is as described in section 3.2. |
| /// ``` |
| pub fn algorithm(&self) -> Algorithm { |
| self.algorithm |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.3) |
| /// |
| /// ```text |
| /// 4.1.3 Labels Field |
| /// |
| /// The "labels" octet is an unsigned count of how many labels there are |
| /// in the original SIG RR owner name not counting the null label for |
| /// root and not counting any initial "*" for a wildcard. If a secured |
| /// retrieval is the result of wild card substitution, it is necessary |
| /// for the resolver to use the original form of the name in verifying |
| /// the digital signature. This field makes it easy to determine the |
| /// original form. |
| /// |
| /// If, on retrieval, the RR appears to have a longer name than indicated |
| /// by "labels", the resolver can tell it is the result of wildcard |
| /// substitution. If the RR owner name appears to be shorter than the |
| /// labels count, the SIG RR must be considered corrupt and ignored. The |
| /// maximum number of labels allowed in the current DNS is 127 but the |
| /// entire octet is reserved and would be required should DNS names ever |
| /// be expanded to 255 labels. The following table gives some examples. |
| /// The value of "labels" is at the top, the retrieved owner name on the |
| /// left, and the table entry is the name to use in signature |
| /// verification except that "bad" means the RR is corrupt. |
| /// |
| /// labels= | 0 | 1 | 2 | 3 | 4 | |
| /// --------+-----+------+--------+----------+----------+ |
| /// .| . | bad | bad | bad | bad | |
| /// d.| *. | d. | bad | bad | bad | |
| /// c.d.| *. | *.d. | c.d. | bad | bad | |
| /// b.c.d.| *. | *.d. | *.c.d. | b.c.d. | bad | |
| /// a.b.c.d.| *. | *.d. | *.c.d. | *.b.c.d. | a.b.c.d. | |
| /// ``` |
| pub fn num_labels(&self) -> u8 { |
| self.num_labels |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.4) |
| /// |
| /// ```text |
| /// 4.1.4 Original TTL Field |
| /// |
| /// The "original TTL" field is included in the RDATA portion to avoid |
| /// (1) authentication problems that caching servers would otherwise |
| /// cause by decrementing the real TTL field and (2) security problems |
| /// that unscrupulous servers could otherwise cause by manipulating the |
| /// real TTL field. This original TTL is protected by the signature |
| /// while the current TTL field is not. |
| /// |
| /// NOTE: The "original TTL" must be restored into the covered RRs when |
| /// the signature is verified (see Section 8). This generally implies |
| /// that all RRs for a particular type, name, and class, that is, all the |
| /// RRs in any particular RRset, must have the same TTL to start with. |
| /// ``` |
| pub fn original_ttl(&self) -> u32 { |
| self.original_ttl |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.5) |
| /// |
| /// ```text |
| /// 4.1.5 Signature Expiration and Inception Fields |
| /// |
| /// The SIG is valid from the "signature inception" time until the |
| /// "signature expiration" time. Both are unsigned numbers of seconds |
| /// since the start of 1 January 1970, GMT, ignoring leap seconds. (See |
| /// also Section 4.4.) Ring arithmetic is used as for DNS SOA serial |
| /// numbers [RFC 1982] which means that these times can never be more |
| /// than about 68 years in the past or the future. This means that these |
| /// times are ambiguous modulo ~136.09 years. However there is no |
| /// security flaw because keys are required to be changed to new random |
| /// keys by [RFC 2541] at least every five years. This means that the |
| /// probability that the same key is in use N*136.09 years later should |
| /// be the same as the probability that a random guess will work. |
| /// |
| /// A SIG RR may have an expiration time numerically less than the |
| /// inception time if the expiration time is near the 32 bit wrap around |
| /// point and/or the signature is long lived. |
| /// |
| /// (To prevent misordering of network requests to update a zone |
| /// dynamically, monotonically increasing "signature inception" times may |
| /// be necessary.) |
| /// |
| /// A secure zone must be considered changed for SOA serial number |
| /// purposes not only when its data is updated but also when new SIG RRs |
| /// are inserted (ie, the zone or any part of it is re-signed). |
| /// ``` |
| pub fn sig_expiration(&self) -> u32 { |
| self.sig_expiration |
| } |
| |
| /// see `get_sig_expiration` |
| pub fn sig_inception(&self) -> u32 { |
| self.sig_inception |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.6) |
| /// |
| /// ```text |
| /// 4.1.6 Key Tag Field |
| /// |
| /// The "key Tag" is a two octet quantity that is used to efficiently |
| /// select between multiple keys which may be applicable and thus check |
| /// that a public key about to be used for the computationally expensive |
| /// effort to check the signature is possibly valid. For algorithm 1 |
| /// (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two |
| /// octets of the public key modulus needed to decode the signature |
| /// field. That is to say, the most significant 16 of the least |
| /// significant 24 bits of the modulus in network (big endian) order. For |
| /// all other algorithms, including private algorithms, it is calculated |
| /// as a simple checksum of the KEY RR as described in Appendix C. |
| /// ``` |
| pub fn key_tag(&self) -> u16 { |
| self.key_tag |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.7) |
| /// |
| /// ```text |
| /// 4.1.7 Signer's Name Field |
| /// |
| /// The "signer's name" field is the domain name of the signer generating |
| /// the SIG RR. This is the owner name of the public KEY RR that can be |
| /// used to verify the signature. It is frequently the zone which |
| /// contained the RRset being authenticated. Which signers should be |
| /// authorized to sign what is a significant resolver policy question as |
| /// discussed in Section 6. The signer's name may be compressed with |
| /// standard DNS name compression when being transmitted over the |
| /// network. |
| /// ``` |
| pub fn signer_name(&self) -> &Name { |
| &self.signer_name |
| } |
| |
| /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.8) |
| /// |
| /// ```text |
| /// 4.1.8 Signature Field |
| /// |
| /// The actual signature portion of the SIG RR binds the other RDATA |
| /// fields to the RRset of the "type covered" RRs with that owner name |
| /// and class. This covered RRset is thereby authenticated. To |
| /// accomplish this, a data sequence is constructed as follows: |
| /// |
| /// data = RDATA | RR(s)... |
| /// |
| /// where "|" is concatenation, |
| /// |
| /// RDATA is the wire format of all the RDATA fields in the SIG RR itself |
| /// (including the canonical form of the signer's name) before but not |
| /// including the signature, and |
| /// |
| /// RR(s) is the RRset of the RR(s) of the type covered with the same |
| /// owner name and class as the SIG RR in canonical form and order as |
| /// defined in Section 8. |
| /// |
| /// How this data sequence is processed into the signature is algorithm |
| /// dependent. These algorithm dependent formats and procedures are |
| /// described in separate documents (Section 3.2). |
| /// |
| /// SIGs SHOULD NOT be included in a zone for any "meta-type" such as |
| /// ANY, AXFR, etc. (but see section 5.6.2 with regard to IXFR). |
| /// ``` |
| pub fn sig(&self) -> &[u8] { |
| &self.sig |
| } |
| } |
| |
| /// Read the RData from the given Decoder |
| pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<SIG> { |
| let start_idx = decoder.index(); |
| |
| // TODO should we verify here? or elsewhere... |
| let type_covered = RecordType::read(decoder)?; |
| let algorithm = Algorithm::read(decoder)?; |
| let num_labels = decoder.read_u8()?.unverified(/*technically valid as any u8*/); |
| let original_ttl = decoder.read_u32()?.unverified(/*valid as any u32*/); |
| let sig_expiration = |
| decoder.read_u32()?.unverified(/*valid as any u32, in practice should be in the future*/); |
| let sig_inception = decoder.read_u32()?.unverified(/*valid as any u32, in practice should be before expiration*/); |
| let key_tag = decoder.read_u16()?.unverified(/*valid as any u16*/); |
| let signer_name = Name::read(decoder)?; |
| |
| // read the signature, this will vary buy key size |
| let sig_len = rdata_length |
| .map(|u| u as usize) |
| .checked_sub(decoder.index() - start_idx) |
| .map_err(|_| ProtoError::from("invalid rdata length in SIG"))? |
| .unverified(/*used only as length safely*/); |
| let sig = decoder |
| .read_vec(sig_len)? |
| .unverified(/*will fail in usage if invalid*/); |
| |
| Ok(SIG::new( |
| type_covered, |
| algorithm, |
| num_labels, |
| original_ttl, |
| sig_expiration, |
| sig_inception, |
| key_tag, |
| signer_name, |
| sig, |
| )) |
| } |
| |
| /// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005 |
| /// |
| /// This is accurate for all currently known name records. |
| /// |
| /// ```text |
| /// 6.2. Canonical RR Form |
| /// |
| /// For the purposes of DNS security, the canonical form of an RR is the |
| /// wire format of the RR where: |
| /// |
| /// ... |
| /// |
| /// 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, |
| /// HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, |
| /// SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase |
| /// US-ASCII letters in the DNS names contained within the RDATA are replaced |
| /// by the corresponding lowercase US-ASCII letters; |
| /// ``` |
| pub fn emit(encoder: &mut BinEncoder, sig: &SIG) -> ProtoResult<()> { |
| let is_canonical_names = encoder.is_canonical_names(); |
| |
| sig.type_covered().emit(encoder)?; |
| sig.algorithm().emit(encoder)?; |
| encoder.emit(sig.num_labels())?; |
| encoder.emit_u32(sig.original_ttl())?; |
| encoder.emit_u32(sig.sig_expiration())?; |
| encoder.emit_u32(sig.sig_inception())?; |
| encoder.emit_u16(sig.key_tag())?; |
| sig.signer_name() |
| .emit_with_lowercase(encoder, is_canonical_names)?; |
| encoder.emit_vec(sig.sig())?; |
| Ok(()) |
| } |
| |
| /// specifically for outputting the RData for an RRSIG, with signer_name in canonical form |
| #[allow(clippy::too_many_arguments)] |
| pub fn emit_pre_sig( |
| encoder: &mut BinEncoder, |
| type_covered: RecordType, |
| algorithm: Algorithm, |
| num_labels: u8, |
| original_ttl: u32, |
| sig_expiration: u32, |
| sig_inception: u32, |
| key_tag: u16, |
| signer_name: &Name, |
| ) -> ProtoResult<()> { |
| type_covered.emit(encoder)?; |
| algorithm.emit(encoder)?; |
| encoder.emit(num_labels)?; |
| encoder.emit_u32(original_ttl)?; |
| encoder.emit_u32(sig_expiration)?; |
| encoder.emit_u32(sig_inception)?; |
| encoder.emit_u16(key_tag)?; |
| signer_name.emit_as_canonical(encoder, true)?; |
| Ok(()) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| #![allow(clippy::dbg_macro, clippy::print_stdout)] |
| |
| use super::*; |
| |
| #[test] |
| fn test() { |
| use std::str::FromStr; |
| |
| let rdata = SIG::new( |
| RecordType::NULL, |
| Algorithm::RSASHA256, |
| 0, |
| 0, |
| 2, |
| 1, |
| 5, |
| Name::from_str("www.example.com").unwrap(), |
| vec![ |
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, |
| 23, 24, 25, 26, 27, 28, 29, 29, 31, |
| ], // 32 bytes for SHA256 |
| ); |
| |
| let mut bytes = Vec::new(); |
| let mut encoder: BinEncoder = BinEncoder::new(&mut bytes); |
| assert!(emit(&mut encoder, &rdata).is_ok()); |
| let bytes = encoder.into_bytes(); |
| |
| println!("bytes: {:?}", bytes); |
| |
| let mut decoder: BinDecoder = BinDecoder::new(bytes); |
| let restrict = Restrict::new(bytes.len() as u16); |
| let read_rdata = read(&mut decoder, restrict).expect("Decoding error"); |
| assert_eq!(rdata, read_rdata); |
| } |
| } |