Skip to main content

hickory_proto/serialize/binary/
decoder.rs

1/*
2 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
18
19use thiserror::Error;
20
21use crate::{
22    rr::{Name, RecordType},
23    serialize::binary::Restrict,
24};
25
26/// This is non-destructive to the inner buffer, b/c for pointer types we need to perform a reverse
27///  seek to lookup names
28///
29/// A note on serialization, there was a thought to have this implement the Serde deserializer,
30///  but given that this is such a small subset of all the serialization which that performs
31///  this is a simpler implementation without the cruft, at least for serializing to/from the
32///  binary DNS protocols.
33pub struct BinDecoder<'a> {
34    buffer: &'a [u8],    // The entire original buffer
35    remaining: &'a [u8], // The unread section of the original buffer, so that reads do not cause a bounds check at the current seek offset
36}
37
38impl<'a> BinDecoder<'a> {
39    /// Creates a new BinDecoder
40    ///
41    /// # Arguments
42    ///
43    /// * `buffer` - buffer from which all data will be read
44    pub fn new(buffer: &'a [u8]) -> Self {
45        BinDecoder {
46            buffer,
47            remaining: buffer,
48        }
49    }
50
51    /// Pop one byte from the buffer
52    pub fn pop(&mut self) -> Result<Restrict<u8>, DecodeError> {
53        if let Some((first, remaining)) = self.remaining.split_first() {
54            self.remaining = remaining;
55            return Ok(Restrict::new(*first));
56        }
57        Err(DecodeError::InsufficientBytes)
58    }
59
60    /// Returns the number of bytes in the buffer
61    ///
62    /// ```
63    /// use hickory_proto::serialize::binary::BinDecoder;
64    ///
65    /// let deadbeef = b"deadbeef";
66    /// let mut decoder = BinDecoder::new(deadbeef);
67    /// assert_eq!(decoder.len(), 8);
68    /// decoder.read_slice(7).unwrap();
69    /// assert_eq!(decoder.len(), 1);
70    /// ```
71    pub fn len(&self) -> usize {
72        self.remaining.len()
73    }
74
75    /// Returns `true` if the buffer is empty
76    pub fn is_empty(&self) -> bool {
77        self.len() == 0
78    }
79
80    /// Peed one byte forward, without moving the current index forward
81    pub fn peek(&self) -> Option<Restrict<u8>> {
82        Some(Restrict::new(*self.remaining.first()?))
83    }
84
85    /// Returns the current index in the buffer
86    pub fn index(&self) -> usize {
87        self.buffer.len() - self.remaining.len()
88    }
89
90    /// This is a pretty efficient clone, as the buffer is never cloned, and only the index is set
91    ///  to the value passed in
92    pub fn clone(&self, index_at: u16) -> Self {
93        BinDecoder {
94            buffer: self.buffer,
95            remaining: &self.buffer[index_at as usize..],
96        }
97    }
98
99    /// Reads a String from the buffer
100    ///
101    /// ```text
102    /// <character-string> is a single
103    /// length octet followed by that number of characters.  <character-string>
104    /// is treated as binary information, and can be up to 256 characters in
105    /// length (including the length octet).
106    /// ```
107    ///
108    /// # Returns
109    ///
110    /// A String version of the character data
111    pub fn read_character_data(&mut self) -> Result<Restrict<&[u8]>, DecodeError> {
112        let length = self.pop()?.unverified() as usize;
113        self.read_slice(length)
114    }
115
116    /// Reads a Vec out of the buffer
117    ///
118    /// # Arguments
119    ///
120    /// * `len` - number of bytes to read from the buffer
121    ///
122    /// # Returns
123    ///
124    /// The Vec of the specified length, otherwise an error
125    pub fn read_vec(&mut self, len: usize) -> Result<Restrict<Vec<u8>>, DecodeError> {
126        self.read_slice(len).map(|s| s.map(ToOwned::to_owned))
127    }
128
129    /// Reads a slice out of the buffer, without allocating
130    ///
131    /// # Arguments
132    ///
133    /// * `len` - number of bytes to read from the buffer
134    ///
135    /// # Returns
136    ///
137    /// The slice of the specified length, otherwise an error
138    pub fn read_slice(&mut self, len: usize) -> Result<Restrict<&'a [u8]>, DecodeError> {
139        if len > self.remaining.len() {
140            return Err(DecodeError::InsufficientBytes);
141        }
142        let (read, remaining) = self.remaining.split_at(len);
143        self.remaining = remaining;
144        Ok(Restrict::new(read))
145    }
146
147    /// Reads a slice from a previous index to the current
148    pub fn slice_from(&self, index: usize) -> Result<&'a [u8], DecodeError> {
149        if index > self.index() {
150            return Err(DecodeError::InvalidPreviousIndex);
151        }
152
153        Ok(&self.buffer[index..self.index()])
154    }
155
156    /// Reads a byte from the buffer, equivalent to `Self::pop()`
157    pub fn read_u8(&mut self) -> Result<Restrict<u8>, DecodeError> {
158        self.pop()
159    }
160
161    /// Reads the next 2 bytes into u16
162    ///
163    /// This performs a byte-by-byte manipulation, there
164    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
165    ///
166    /// # Return
167    ///
168    /// Return the u16 from the buffer
169    pub fn read_u16(&mut self) -> Result<Restrict<u16>, DecodeError> {
170        Ok(self
171            .read_slice(2)?
172            .map(|s| u16::from_be_bytes([s[0], s[1]])))
173    }
174
175    /// Reads the next four bytes into i32.
176    ///
177    /// This performs a byte-by-byte manipulation, there
178    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
179    ///
180    /// # Return
181    ///
182    /// Return the i32 from the buffer
183    pub fn read_i32(&mut self) -> Result<Restrict<i32>, DecodeError> {
184        Ok(self.read_slice(4)?.map(|s| {
185            assert!(s.len() == 4);
186            i32::from_be_bytes([s[0], s[1], s[2], s[3]])
187        }))
188    }
189
190    /// Reads the next four bytes into u32.
191    ///
192    /// This performs a byte-by-byte manipulation, there
193    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
194    ///
195    /// # Return
196    ///
197    /// Return the u32 from the buffer
198    pub fn read_u32(&mut self) -> Result<Restrict<u32>, DecodeError> {
199        Ok(self.read_slice(4)?.map(|s| {
200            assert!(s.len() == 4);
201            u32::from_be_bytes([s[0], s[1], s[2], s[3]])
202        }))
203    }
204}
205
206/// An error that can occur deep in a decoder
207/// This type is kept very small so that function that use it inline often
208#[derive(Clone, Debug, Error)]
209#[non_exhaustive]
210pub enum DecodeError {
211    /// DNS key protocol version doesn't have the expected version 3
212    #[cfg(feature = "__dnssec")]
213    #[error("dns key value unknown, must be 3: {0}")]
214    DnsKeyProtocolNot3(u8),
215
216    /// Reserved KEY flags are set
217    #[cfg(feature = "__dnssec")]
218    #[error("KEY flags reserved bits are set: {0:#06x}")]
219    KeyFlagsReserved(u16),
220
221    /// Extended KEY flags are not supported
222    #[cfg(feature = "__dnssec")]
223    #[error("extended KEY flags not supported")]
224    ExtendedKeyFlagsUnsupported(u16),
225
226    /// EDNS resource record label is not the root label, although required
227    #[error("edns resource record label must be the root label (.): {0}")]
228    EdnsNameNotRoot(Box<Name>),
229
230    /// The length of rdata read was not as expected
231    #[non_exhaustive]
232    #[error("incorrect rdata length read: {read} expected: {len}")]
233    IncorrectRDataLengthRead {
234        /// The amount of read data
235        read: usize,
236        /// The expected length of the data
237        len: usize,
238    },
239
240    /// Insufficient data in the buffer for a read operation
241    #[error("unexpected end of input reached")]
242    InsufficientBytes,
243
244    /// Invalid record with data length 0 in non-update message
245    #[error("unexpected record with length 0 in non-update message")]
246    InvalidEmptyRecord,
247
248    /// slice_from was called with an invalid index
249    #[error("the index passed to BinDecoder::slice_from must be greater than the decoder position")]
250    InvalidPreviousIndex,
251
252    /// Pointer points to an index within or after the current name
253    #[error("label points to data not prior to idx: {idx} ptr: {ptr}")]
254    PointerNotPriorToLabel {
255        /// index of the label containing this pointer
256        idx: usize,
257        /// location to which the pointer is directing
258        ptr: u16,
259    },
260
261    /// Label bytes exceeded the limit of 63
262    #[error("label bytes exceed 63: {0}")]
263    LabelBytesTooLong(usize),
264
265    /// An unrecognized label code was found
266    #[error("unrecognized label code: {0:b}")]
267    UnrecognizedLabelCode(u8),
268
269    /// A domain name was too long
270    #[error("name label data exceed 255: {0}")]
271    DomainNameTooLong(usize),
272
273    /// Overlapping labels
274    #[error("overlapping labels name {label} other {other}")]
275    LabelOverlapsWithOther {
276        /// Start of the label that is overlaps
277        label: usize,
278        /// Start of the other label
279        other: usize,
280    },
281
282    /// An unknown digest algorithm was found
283    #[error("unknown digest algorithm: {0}")]
284    UnknownDigestAlgorithm(u8),
285
286    /// An unknown dns class was found
287    #[error("dns class string unknown: {0}")]
288    UnknownDnsClassStr(String),
289
290    /// An unknown dns class value was found
291    #[error("dns class value unknown: {0}")]
292    UnknownDnsClassValue(u16),
293
294    /// An unknown record type string was found
295    #[error("record type string unknown: {0}")]
296    UnknownRecordTypeStr(String),
297
298    /// An unknown record type value was found
299    #[error("record type value unknown: {0}")]
300    UnknownRecordTypeValue(u16),
301
302    /// Unrecognized nsec3 flags were found
303    #[error("nsec3 flags should be 0b0000000*: {0:b}")]
304    UnrecognizedNsec3Flags(u8),
305
306    /// Unrecognized csync flags were found
307    #[error("csync flags should be 0b000000**: {0:b}")]
308    UnrecognizedCsyncFlags(u16),
309
310    /// An unknown algorithm type was found
311    #[error("unknown NSEC3 hash algorithm: {0}")]
312    UnknownNsec3HashAlgorithm(u8),
313
314    /// A record appeared after TSIG or SIG(0)
315    #[error("record after TSIG or SIG(0)")]
316    RecordAfterSig,
317
318    /// A record type was found outside the additional section
319    #[error("record type {0} only allowed in additional section")]
320    RecordNotInAdditionalSection(RecordType),
321
322    /// More than one EDNS record was found
323    #[error("more than one EDNS record")]
324    DuplicateEdns,
325
326    /// SvcParams were not in strictly increasing order
327    #[error("SvcParams out of order")]
328    SvcParamsOutOfOrder,
329
330    /// An SvcParam was expected to contain at least one value
331    #[error("SvcParam expects at least one value")]
332    SvcParamMissingValue,
333
334    /// NSEC or NSEC3 bitmap data was out of bounds
335    #[error("NSEC bitmap out of bounds")]
336    NsecBitmapOutOfBounds,
337
338    /// CAA tag was invalid (length or characters out of bounds)
339    #[error("CAA tag invalid")]
340    CaaTagInvalid,
341
342    /// NAPTR flags contained characters outside [a-zA-Z0-9]
343    #[error("NAPTR flags not in range [a-zA-Z0-9]")]
344    NaptrFlagsInvalid,
345
346    /// An unknown address family was found
347    #[error("unknown address family: {0:#x}")]
348    UnknownAddressFamily(u16),
349
350    /// Invalid UTF-8 data
351    #[error("invalid UTF-8: {0}")]
352    Utf8(#[from] alloc::string::FromUtf8Error),
353}
354
355#[cfg(test)]
356mod tests {
357    use super::*;
358
359    #[test]
360    fn test_read_slice() {
361        let deadbeef = b"deadbeef";
362        let mut decoder = BinDecoder::new(deadbeef);
363
364        let read = decoder.read_slice(4).expect("failed to read dead");
365        assert_eq!(&read.unverified(), b"dead");
366
367        let read = decoder.read_slice(2).expect("failed to read be");
368        assert_eq!(&read.unverified(), b"be");
369
370        let read = decoder.read_slice(0).expect("failed to read nothing");
371        assert_eq!(&read.unverified(), b"");
372
373        // this should fail
374        assert!(decoder.read_slice(3).is_err());
375    }
376
377    #[test]
378    fn test_read_slice_from() {
379        let deadbeef = b"deadbeef";
380        let mut decoder = BinDecoder::new(deadbeef);
381
382        decoder.read_slice(4).expect("failed to read dead");
383        let read = decoder.slice_from(0).expect("failed to get slice");
384        assert_eq!(&read, b"dead");
385
386        decoder.read_slice(2).expect("failed to read be");
387        let read = decoder.slice_from(4).expect("failed to get slice");
388        assert_eq!(&read, b"be");
389
390        decoder.read_slice(0).expect("failed to read nothing");
391        let read = decoder.slice_from(4).expect("failed to get slice");
392        assert_eq!(&read, b"be");
393
394        // this should fail
395        assert!(decoder.slice_from(10).is_err());
396    }
397}