1 //! Parsing the DNS wire protocol.
2 
3 pub(crate) use std::io::Cursor;
4 pub(crate) use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
5 
6 use std::io;
7 use log::*;
8 
9 use crate::record::{Record, OPT};
10 use crate::strings::{Labels, ReadLabels, WriteLabels};
11 use crate::types::*;
12 
13 
14 impl Request {
15 
16     /// Converts this request to a vector of bytes.
to_bytes(&self) -> io::Result<Vec<u8>>17     pub fn to_bytes(&self) -> io::Result<Vec<u8>> {
18         let mut bytes = Vec::with_capacity(32);
19 
20         bytes.write_u16::<BigEndian>(self.transaction_id)?;
21         bytes.write_u16::<BigEndian>(self.flags.to_u16())?;
22 
23         bytes.write_u16::<BigEndian>(1)?;  // query count
24         bytes.write_u16::<BigEndian>(0)?;  // answer count
25         bytes.write_u16::<BigEndian>(0)?;  // authority RR count
26         bytes.write_u16::<BigEndian>(if self.additional.is_some() { 1 } else { 0 })?;  // additional RR count
27 
28         bytes.write_labels(&self.query.qname)?;
29         bytes.write_u16::<BigEndian>(self.query.qtype)?;
30         bytes.write_u16::<BigEndian>(self.query.qclass.to_u16())?;
31 
32         if let Some(opt) = &self.additional {
33             bytes.write_u8(0)?;  // usually a name
34             bytes.write_u16::<BigEndian>(OPT::RR_TYPE)?;
35             bytes.extend(opt.to_bytes()?);
36         }
37 
38         Ok(bytes)
39     }
40 
41     /// Returns the OPT record to be sent as part of requests.
additional_record() -> OPT42     pub fn additional_record() -> OPT {
43         OPT {
44             udp_payload_size: 512,
45             higher_bits: 0,
46             edns0_version: 0,
47             flags: 0,
48             data: Vec::new(),
49         }
50     }
51 }
52 
53 
54 impl Response {
55 
56     /// Reads bytes off of the given slice, parsing them into a response.
57     #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
from_bytes(bytes: &[u8]) -> Result<Self, WireError>58     pub fn from_bytes(bytes: &[u8]) -> Result<Self, WireError> {
59         info!("Parsing response");
60         trace!("Bytes -> {:?}", bytes);
61         let mut c = Cursor::new(bytes);
62 
63         let transaction_id = c.read_u16::<BigEndian>()?;
64         trace!("Read txid -> {:?}", transaction_id);
65 
66         let flags = Flags::from_u16(c.read_u16::<BigEndian>()?);
67         trace!("Read flags -> {:#?}", flags);
68 
69         let query_count      = c.read_u16::<BigEndian>()?;
70         let answer_count     = c.read_u16::<BigEndian>()?;
71         let authority_count  = c.read_u16::<BigEndian>()?;
72         let additional_count = c.read_u16::<BigEndian>()?;
73 
74         let mut queries = Vec::new();
75         debug!("Reading {}x query from response", query_count);
76         for _ in 0 .. query_count {
77             let (qname, _) = c.read_labels()?;
78             queries.push(Query::from_bytes(qname, &mut c)?);
79         }
80 
81         let mut answers = Vec::new();
82         debug!("Reading {}x answer from response", answer_count);
83         for _ in 0 .. answer_count {
84             let (qname, _) = c.read_labels()?;
85             answers.push(Answer::from_bytes(qname, &mut c)?);
86         }
87 
88         let mut authorities = Vec::new();
89         debug!("Reading {}x authority from response", authority_count);
90         for _ in 0 .. authority_count {
91             let (qname, _) = c.read_labels()?;
92             authorities.push(Answer::from_bytes(qname, &mut c)?);
93         }
94 
95         let mut additionals = Vec::new();
96         debug!("Reading {}x additional answer from response", additional_count);
97         for _ in 0 .. additional_count {
98             let (qname, _) = c.read_labels()?;
99             additionals.push(Answer::from_bytes(qname, &mut c)?);
100         }
101 
102         Ok(Self { transaction_id, flags, queries, answers, authorities, additionals })
103     }
104 }
105 
106 
107 impl Query {
108 
109     /// Reads bytes from the given cursor, and parses them into a query with
110     /// the given domain name.
111     #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
from_bytes(qname: Labels, c: &mut Cursor<&[u8]>) -> Result<Self, WireError>112     fn from_bytes(qname: Labels, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
113         let qtype = c.read_u16::<BigEndian>()?;
114         trace!("Read qtype -> {:?}", qtype);
115 
116         let qclass = QClass::from_u16(c.read_u16::<BigEndian>()?);
117         trace!("Read qclass -> {:?}", qtype);
118 
119         Ok(Self { qtype, qclass, qname })
120     }
121 }
122 
123 
124 impl Answer {
125 
126     /// Reads bytes from the given cursor, and parses them into an answer with
127     /// the given domain name.
128     #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
from_bytes(qname: Labels, c: &mut Cursor<&[u8]>) -> Result<Self, WireError>129     fn from_bytes(qname: Labels, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
130         let qtype = c.read_u16::<BigEndian>()?;
131         trace!("Read qtype -> {:?}", qtype);
132 
133         if qtype == OPT::RR_TYPE {
134             let opt = OPT::read(c)?;
135             Ok(Self::Pseudo { qname, opt })
136         }
137         else {
138             let qclass = QClass::from_u16(c.read_u16::<BigEndian>()?);
139             trace!("Read qclass -> {:?}", qtype);
140 
141             let ttl = c.read_u32::<BigEndian>()?;
142             trace!("Read TTL -> {:?}", ttl);
143 
144             let record_length = c.read_u16::<BigEndian>()?;
145             trace!("Read record length -> {:?}", record_length);
146 
147             let record = Record::from_bytes(qtype, record_length, c)?;
148             Ok(Self::Standard { qclass, qname, record, ttl })
149         }
150 
151     }
152 }
153 
154 
155 impl Record {
156 
157     /// Reads at most `len` bytes from the given curser, and parses them into
158     /// a record structure depending on the type number, which has already been read.
159     #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
from_bytes(qtype: TypeInt, len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError>160     fn from_bytes(qtype: TypeInt, len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
161         use crate::record::*;
162 
163         macro_rules! try_record {
164             ($record:tt) => {
165                 if $record::RR_TYPE == qtype {
166                     info!("Parsing {} record (type {}, len {})", $record::NAME, qtype, len);
167                     return Wire::read(len, c).map(Self::$record)
168                 }
169             }
170         }
171 
172         // Try all the records, one type at a time, returning early if the
173         // type number matches.
174         try_record!(A);
175         try_record!(AAAA);
176         try_record!(CAA);
177         try_record!(CNAME);
178         try_record!(HINFO);
179         try_record!(LOC);
180         try_record!(MX);
181         try_record!(NAPTR);
182         try_record!(NS);
183         // OPT is handled separately
184         try_record!(PTR);
185         try_record!(SSHFP);
186         try_record!(SOA);
187         try_record!(SRV);
188         try_record!(TLSA);
189         try_record!(TXT);
190 
191         // Otherwise, collect the bytes into a vector and return an unknown
192         // record type.
193         let mut bytes = Vec::new();
194         for _ in 0 .. len {
195             bytes.push(c.read_u8()?);
196         }
197 
198         let type_number = UnknownQtype::from(qtype);
199         Ok(Self::Other { type_number, bytes })
200     }
201 }
202 
203 
204 impl QClass {
from_u16(uu: u16) -> Self205     fn from_u16(uu: u16) -> Self {
206         match uu {
207             0x0001 => Self::IN,
208             0x0003 => Self::CH,
209             0x0004 => Self::HS,
210                  _ => Self::Other(uu),
211         }
212     }
213 
to_u16(self) -> u16214     fn to_u16(self) -> u16 {
215         match self {
216             Self::IN        => 0x0001,
217             Self::CH        => 0x0003,
218             Self::HS        => 0x0004,
219             Self::Other(uu) => uu,
220         }
221     }
222 }
223 
224 
225 /// Determines the record type number to signify a record with the given name.
find_qtype_number(record_type: &str) -> Option<TypeInt>226 pub fn find_qtype_number(record_type: &str) -> Option<TypeInt> {
227     use crate::record::*;
228 
229     macro_rules! try_record {
230         ($record:tt) => {
231             if $record::NAME == record_type {
232                 return Some($record::RR_TYPE);
233             }
234         }
235     }
236 
237     try_record!(A);
238     try_record!(AAAA);
239     try_record!(CAA);
240     try_record!(CNAME);
241     try_record!(HINFO);
242     try_record!(LOC);
243     try_record!(MX);
244     try_record!(NAPTR);
245     try_record!(NS);
246     // OPT is elsewhere
247     try_record!(PTR);
248     try_record!(SSHFP);
249     try_record!(SOA);
250     try_record!(SRV);
251     try_record!(TLSA);
252     try_record!(TXT);
253 
254     None
255 }
256 
257 
258 impl Flags {
259 
260     /// The set of flags that represents a query packet.
query() -> Self261     pub fn query() -> Self {
262         Self::from_u16(0b_0000_0001_0000_0000)
263     }
264 
265     /// The set of flags that represents a successful response.
standard_response() -> Self266     pub fn standard_response() -> Self {
267         Self::from_u16(0b_1000_0001_1000_0000)
268     }
269 
270     /// Converts the flags into a two-byte number.
to_u16(self) -> u16271     pub fn to_u16(self) -> u16 {                 // 0123 4567 89AB CDEF
272         let mut                          bits  = 0b_0000_0000_0000_0000;
273         if self.response               { bits += 0b_1000_0000_0000_0000; }
274         match self.opcode {
275             Opcode::Query     =>       { bits += 0b_0000_0000_0000_0000; }
276             Opcode::Other(_)  =>       { unimplemented!(); }
277         }
278         if self.authoritative          { bits += 0b_0000_0100_0000_0000; }
279         if self.truncated              { bits += 0b_0000_0010_0000_0000; }
280         if self.recursion_desired      { bits += 0b_0000_0001_0000_0000; }
281         if self.recursion_available    { bits += 0b_0000_0000_1000_0000; }
282         // (the Z bit is reserved)               0b_0000_0000_0100_0000
283         if self.authentic_data         { bits += 0b_0000_0000_0010_0000; }
284         if self.checking_disabled      { bits += 0b_0000_0000_0001_0000; }
285 
286         bits
287     }
288 
289     /// Extracts the flags from the given two-byte number.
from_u16(bits: u16) -> Self290     pub fn from_u16(bits: u16) -> Self {
291         let has_bit = |bit| { bits & bit == bit };
292 
293         Self {
294             response:               has_bit(0b_1000_0000_0000_0000),
295             opcode:                 Opcode::from_bits((bits.to_be_bytes()[0] & 0b_0111_1000) >> 3),
296             authoritative:          has_bit(0b_0000_0100_0000_0000),
297             truncated:              has_bit(0b_0000_0010_0000_0000),
298             recursion_desired:      has_bit(0b_0000_0001_0000_0000),
299             recursion_available:    has_bit(0b_0000_0000_1000_0000),
300             authentic_data:         has_bit(0b_0000_0000_0010_0000),
301             checking_disabled:      has_bit(0b_0000_0000_0001_0000),
302             error_code:             ErrorCode::from_bits(bits & 0b_1111),
303         }
304     }
305 }
306 
307 
308 impl Opcode {
309 
310     /// Extracts the opcode from this four-bit number, which should have been
311     /// extracted from the packet and shifted to be in the range 0–15.
from_bits(bits: u8) -> Self312     fn from_bits(bits: u8) -> Self {
313         if bits == 0 {
314             Self::Query
315         }
316         else {
317             assert!(bits <= 15, "bits {:#08b} out of range", bits);
318             Self::Other(bits)
319         }
320     }
321 }
322 
323 
324 impl ErrorCode {
325 
326     /// Extracts the rcode from the last four bits of the flags field.
from_bits(bits: u16) -> Option<Self>327     fn from_bits(bits: u16) -> Option<Self> {
328         if (0x0F01 .. 0x0FFF).contains(&bits) {
329             return Some(Self::Private(bits));
330         }
331 
332         match bits {
333             0 => None,
334             1 => Some(Self::FormatError),
335             2 => Some(Self::ServerFailure),
336             3 => Some(Self::NXDomain),
337             4 => Some(Self::NotImplemented),
338             5 => Some(Self::QueryRefused),
339            16 => Some(Self::BadVersion),
340             n => Some(Self::Other(n)),
341         }
342     }
343 }
344 
345 
346 /// Trait for decoding DNS record structures from bytes read over the wire.
347 pub trait Wire: Sized {
348 
349     /// This record’s type as a string, such as `"A"` or `"CNAME"`.
350     const NAME: &'static str;
351 
352     /// The number signifying that a record is of this type.
353     /// See <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4>
354     const RR_TYPE: u16;
355 
356     /// Read at most `len` bytes from the given `Cursor`. This cursor travels
357     /// throughout the complete data — by this point, we have read the entire
358     /// response into a buffer.
read(len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError>359     fn read(len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError>;
360 }
361 
362 
363 /// Helper macro to get the qtype number of a record type at compile-time.
364 ///
365 /// # Examples
366 ///
367 /// ```
368 /// use dns::{qtype, record::MX};
369 ///
370 /// assert_eq!(15, qtype!(MX));
371 /// ```
372 #[macro_export]
373 macro_rules! qtype {
374     ($type:ty) => {
375         <$type as $crate::Wire>::RR_TYPE
376     }
377 }
378 
379 
380 /// Something that can go wrong deciphering a record.
381 #[derive(PartialEq, Debug)]
382 pub enum WireError {
383 
384     /// There was an IO error reading from the cursor.
385     /// Almost all the time, this means that the buffer was too short.
386     IO,
387     // (io::Error is not PartialEq so we don’t propagate it)
388 
389     /// When the DNS standard requires records of this type to have a certain
390     /// fixed length, but the response specified a different length.
391     ///
392     /// This error should be returned regardless of the _content_ of the
393     /// record, whatever it is.
394     WrongRecordLength {
395 
396         /// The length of the record’s data, as specified in the packet.
397         stated_length: u16,
398 
399         /// The length of the record that the DNS specification mandates.
400         mandated_length: MandatedLength,
401     },
402 
403     /// When the length of this record as specified in the packet differs from
404     /// the computed length, as determined by reading labels.
405     ///
406     /// There are two ways, in general, to read arbitrary-length data from a
407     /// stream of bytes: length-prefixed (read the length, then read that many
408     /// bytes) or sentinel-terminated (keep reading bytes until you read a
409     /// certain value, usually zero). The DNS protocol uses both: each
410     /// record’s size is specified up-front in the packet, but inside the
411     /// record, there exist arbitrary-length strings that must be read until a
412     /// zero is read, indicating there is no more string.
413     ///
414     /// Consider the case of a packet, with a specified length, containing a
415     /// string of arbitrary length (such as the CNAME or TXT records). A DNS
416     /// client has to deal with this in one of two ways:
417     ///
418     /// 1. Read exactly the specified length of bytes from the record, raising
419     ///    an error if the contents are too short or a string keeps going past
420     ///    the length (assume the length is correct but the contents are wrong).
421     ///
422     /// 2. Read as many bytes from the record as the string requests, raising
423     ///    an error if the number of bytes read at the end differs from the
424     ///    expected length of the record (assume the length is wrong but the
425     ///    contents are correct).
426     ///
427     /// Note that no matter which way is picked, the record will still be
428     /// incorrect — it only impacts the parsing of records that occur after it
429     /// in the packet. Knowing which method should be used requires knowing
430     /// what caused the DNS packet to be erroneous, which we cannot know.
431     ///
432     /// dog picks the second way. If a record ends up reading more or fewer
433     /// bytes than it is ‘supposed’ to, it will raise this error, but _after_
434     /// having read a different number of bytes than the specified length.
435     WrongLabelLength {
436 
437         /// The length of the record’s data, as specified in the packet.
438         stated_length: u16,
439 
440         /// The computed length of the record’s data, based on the number of
441         /// bytes consumed by reading labels from the packet.
442         length_after_labels: u16,
443     },
444 
445     /// When the data contained a string containing a cycle of pointers.
446     /// Contains the vector of indexes that was being checked.
447     TooMuchRecursion(Vec<u16>),
448 
449     /// When the data contained a string with a pointer to an index outside of
450     /// the packet. Contains the invalid index.
451     OutOfBounds(u16),
452 
453     /// When a record in the packet contained a version field that specifies
454     /// the format of its remaining fields, but this version is too recent to
455     /// be supported, so we cannot parse it.
456     WrongVersion {
457 
458         /// The version of the record layout, as specified in the packet
459         stated_version: u8,
460 
461         /// The maximum version that this version of dog supports.
462         maximum_supported_version: u8,
463     }
464 }
465 
466 /// The rule for how long a record in a packet should be.
467 #[derive(PartialEq, Debug, Copy, Clone)]
468 pub enum MandatedLength {
469 
470     /// The record should be exactly this many bytes in length.
471     Exactly(u16),
472 
473     /// The record should be _at least_ this many bytes in length.
474     AtLeast(u16),
475 }
476 
477 impl From<io::Error> for WireError {
from(ioe: io::Error) -> Self478     fn from(ioe: io::Error) -> Self {
479         error!("IO error -> {:?}", ioe);
480         Self::IO
481     }
482 }
483 
484 
485 #[cfg(test)]
486 mod test {
487     use super::*;
488     use crate::record::{Record, A, SOA, OPT, UnknownQtype};
489     use std::net::Ipv4Addr;
490     use pretty_assertions::assert_eq;
491 
492     #[test]
build_request()493     fn build_request() {
494         let request = Request {
495             transaction_id: 0xceac,
496             flags: Flags::query(),
497             query: Query {
498                 qname: Labels::encode("rfcs.io").unwrap(),
499                 qclass: QClass::Other(0x42),
500                 qtype: 0x1234,
501             },
502             additional: Some(Request::additional_record()),
503         };
504 
505         let result = vec![
506             0xce, 0xac,  // transaction ID
507             0x01, 0x00,  // flags (standard query)
508             0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,  // counts (1, 0, 0, 1)
509 
510             // query:
511             0x04, 0x72, 0x66, 0x63, 0x73, 0x02, 0x69, 0x6f, 0x00,  // qname
512             0x12, 0x34,  // type
513             0x00, 0x42,  // class
514 
515             // OPT record:
516             0x00,  // name
517             0x00, 0x29,  // type OPT
518             0x02, 0x00,  // UDP payload size
519             0x00,  // higher bits
520             0x00,  // EDNS(0) version
521             0x00, 0x00,  // more flags
522             0x00, 0x00,  // no data
523         ];
524 
525         assert_eq!(request.to_bytes().unwrap(), result);
526     }
527 
528     #[test]
complete_response()529     fn complete_response() {
530 
531         // This is an artifical amalgam of DNS, not a real-world response!
532         let buf = &[
533             0xce, 0xac,  // transaction ID
534             0x81, 0x80,  // flags (standard query, response, no error)
535             0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02,  // counts (1, 1, 1, 2)
536 
537             // query:
538             0x05, 0x62, 0x73, 0x61, 0x67, 0x6f, 0x02, 0x6d, 0x65, 0x00,  // name
539             0x00, 0x01,  // type A
540             0x00, 0x01,  // class IN
541 
542             // answer:
543             0xc0, 0x0c,  // name (backreference)
544             0x00, 0x01,  // type A
545             0x00, 0x01,  // class IN
546             0x00, 0x00, 0x03, 0x77,  // TTL
547             0x00, 0x04,  // data length 4
548             0x8a, 0x44, 0x75, 0x5e,  // IP address
549 
550             // authoritative:
551             0x00,  // name
552             0x00, 0x06,  // type SOA
553             0x00, 0x01,  // class IN
554             0xFF, 0xFF, 0xFF, 0xFF,  // TTL (maximum possible!)
555             0x00, 0x1B,  // data length
556             0x01, 0x61, 0x00,  // primary name server ("a")
557             0x02, 0x6d, 0x78, 0x00,  // mailbox ("mx")
558             0x78, 0x68, 0x52, 0x2c,  // serial number
559             0x00, 0x00, 0x07, 0x08,  // refresh interval
560             0x00, 0x00, 0x03, 0x84,  // retry interval
561             0x00, 0x09, 0x3a, 0x80,  // expire limit
562             0x00, 0x01, 0x51, 0x80,  // minimum TTL
563 
564             // additional 1:
565             0x00,  // name
566             0x00, 0x99,  // unknown type
567             0x00, 0x99,  // unknown class
568             0x12, 0x34, 0x56, 0x78,  // TTL
569             0x00, 0x04,  // data length 4
570             0x12, 0x34, 0x56, 0x78,  // data
571 
572             // additional 2:
573             0x00,  // name
574             0x00, 0x29,  // type OPT
575             0x02, 0x00,  // UDP payload size
576             0x00,  // higher bits
577             0x00,  // EDNS(0) version
578             0x00, 0x00,  // more flags
579             0x00, 0x00,  // no data
580         ];
581 
582         let response = Response {
583             transaction_id: 0xceac,
584             flags: Flags::standard_response(),
585             queries: vec![
586                 Query {
587                     qname: Labels::encode("bsago.me").unwrap(),
588                     qclass: QClass::IN,
589                     qtype: qtype!(A),
590                 },
591             ],
592             answers: vec![
593                 Answer::Standard {
594                     qname: Labels::encode("bsago.me").unwrap(),
595                     qclass: QClass::IN,
596                     ttl: 887,
597                     record: Record::A(A {
598                         address: Ipv4Addr::new(138, 68, 117, 94),
599                     }),
600                 }
601             ],
602             authorities: vec![
603                 Answer::Standard {
604                     qname: Labels::root(),
605                     qclass: QClass::IN,
606                     ttl: 4294967295,
607                     record: Record::SOA(SOA {
608                         mname: Labels::encode("a").unwrap(),
609                         rname: Labels::encode("mx").unwrap(),
610                         serial: 2020102700,
611                         refresh_interval: 1800,
612                         retry_interval: 900,
613                         expire_limit: 604800,
614                         minimum_ttl: 86400,
615                     }),
616                 }
617             ],
618             additionals: vec![
619                 Answer::Standard {
620                     qname: Labels::root(),
621                     qclass: QClass::Other(153),
622                     ttl: 305419896,
623                     record: Record::Other {
624                         type_number: UnknownQtype::UnheardOf(153),
625                         bytes: vec![ 0x12, 0x34, 0x56, 0x78 ],
626                     },
627                 },
628                 Answer::Pseudo {
629                     qname: Labels::root(),
630                     opt: OPT {
631                         udp_payload_size: 512,
632                         higher_bits: 0,
633                         edns0_version: 0,
634                         flags: 0,
635                         data: vec![],
636                     },
637                 },
638             ],
639         };
640 
641         assert_eq!(Response::from_bytes(buf), Ok(response));
642     }
643 }
644