Skip to main content

hickory_server/zone_handler/
message_response.rs

1// Copyright 2015-2021 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use tracing::{debug, error};
9
10use crate::{
11    net::{udp::MAX_RECEIVE_BUFFER_SIZE, xfer::Protocol},
12    proto::{
13        ProtoError,
14        op::{
15            Edns, Header, HeaderCounts, MessageType, Metadata, OpCode, ResponseCode,
16            emit_message_parts,
17        },
18        rr::{Record, rdata::TSIG},
19        serialize::binary::{BinEncodable, BinEncoder},
20    },
21    server::ResponseInfo,
22    zone_handler::{Queries, message_request::MessageRequest},
23};
24
25/// A [`crate::proto::serialize::binary::BinEncodable`] message with borrowed data for
26/// Responses in the Server
27///
28/// This can be constructed via [`MessageResponseBuilder`].
29#[derive(Debug)]
30pub struct MessageResponse<'q, 'a, Answers, Authorities, Soa, Additionals>
31where
32    Answers: Iterator<Item = &'a Record> + Send + 'a,
33    Authorities: Iterator<Item = &'a Record> + Send + 'a,
34    Soa: Iterator<Item = &'a Record> + Send + 'a,
35    Additionals: Iterator<Item = &'a Record> + Send + 'a,
36{
37    metadata: Metadata,
38    queries: &'q Queries,
39    answers: Answers,
40    authorities: Authorities,
41    soa: Soa,
42    additionals: Additionals,
43    signature: Option<Box<Record<TSIG>>>,
44    edns: Option<&'q Edns>,
45}
46
47impl<'q, 'a, A, N, S, D> MessageResponse<'q, 'a, A, N, S, D>
48where
49    A: Iterator<Item = &'a Record> + Send + 'a,
50    N: Iterator<Item = &'a Record> + Send + 'a,
51    S: Iterator<Item = &'a Record> + Send + 'a,
52    D: Iterator<Item = &'a Record> + Send + 'a,
53{
54    /// Returns the header of the message
55    pub fn metadata(&self) -> &Metadata {
56        &self.metadata
57    }
58
59    /// Get a mutable reference to the header
60    pub fn metadata_mut(&mut self) -> &mut Metadata {
61        &mut self.metadata
62    }
63
64    /// Set the EDNS options for the Response
65    pub fn set_edns(&mut self, edns: &'q Edns) -> &mut Self {
66        self.edns = Some(edns);
67        self
68    }
69
70    /// Gets a reference to the EDNS options for the Response.
71    pub fn edns(&self) -> Option<&'q Edns> {
72        self.edns
73    }
74
75    /// Set the message signature
76    pub fn set_signature(&mut self, signature: Box<Record<TSIG>>) {
77        self.signature = Some(signature);
78    }
79
80    pub(crate) fn encode(self, protocol: Protocol) -> Result<(ResponseInfo, Vec<u8>), ProtoError> {
81        let id = self.metadata.id;
82        debug!(
83            id,
84            response_code = %self.metadata.response_code,
85            "encoding response"
86        );
87
88        let mut bytes = Vec::with_capacity(512);
89        let mut encoder = BinEncoder::new(&mut bytes);
90        encoder.set_max_size(match protocol {
91            Protocol::Udp => match &self.edns {
92                Some(edns) => edns.max_payload(),
93                // No EDNS, use the recommended max from RFC 6891
94                None => MAX_RECEIVE_BUFFER_SIZE as u16,
95            },
96            _ => u16::MAX,
97        });
98
99        let error = match self.destructive_emit(&mut encoder) {
100            Ok(info) => return Ok((info, bytes)),
101            Err(error) => error,
102        };
103
104        error!(%error, "error encoding message");
105        bytes.clear();
106        let mut encoder = BinEncoder::new(&mut bytes);
107        encoder.set_max_size(512);
108
109        let mut metadata = Metadata::new(id, MessageType::Response, OpCode::Query);
110        metadata.response_code = ResponseCode::ServFail;
111        let header = Header {
112            metadata,
113            counts: HeaderCounts::default(),
114        };
115
116        header.emit(&mut encoder)?;
117        Ok((ResponseInfo::from(header), bytes))
118    }
119
120    /// Consumes self, and emits to the encoder.
121    pub fn destructive_emit(
122        mut self,
123        encoder: &mut BinEncoder<'_>,
124    ) -> Result<ResponseInfo, ProtoError> {
125        // soa records are part of the authority section
126        let mut authorities = self.authorities.chain(self.soa);
127
128        let header = emit_message_parts(
129            &self.metadata,
130            &mut self.queries.as_emit_and_count(),
131            &mut self.answers,
132            &mut authorities,
133            &mut self.additionals,
134            self.edns,
135            self.signature.as_deref(),
136            encoder,
137        )?;
138
139        Ok(ResponseInfo::from(header))
140    }
141}
142
143/// A builder for MessageResponses
144pub struct MessageResponseBuilder<'q> {
145    queries: &'q Queries,
146    signature: Option<Box<Record<TSIG>>>,
147    edns: Option<&'q Edns>,
148}
149
150impl<'q> MessageResponseBuilder<'q> {
151    /// Constructs a new response builder
152    ///
153    /// # Arguments
154    ///
155    /// * `queries` - queries (from the Request) to associate with the Response
156    /// * `edns` - Optional Edns data to associate with the Response
157    pub fn new(queries: &'q Queries, edns: Option<&'q Edns>) -> Self {
158        MessageResponseBuilder {
159            queries,
160            signature: None,
161            edns,
162        }
163    }
164
165    /// Constructs a new response builder
166    ///
167    /// # Arguments
168    ///
169    /// * `message` - original request message to associate with the response
170    ///
171    /// # Example
172    ///
173    /// ```rust
174    /// use hickory_proto::{op::ResponseCode, rr::Record};
175    /// use hickory_server::{
176    ///     server::Request,
177    ///     zone_handler::{MessageResponse, MessageResponseBuilder},
178    /// };
179    ///
180    /// fn handle_request<'q>(request: &'q Request) -> MessageResponse<
181    ///     'q,
182    ///     'static,
183    ///     impl Iterator<Item = &'static Record> + Send + 'static,
184    ///     impl Iterator<Item = &'static Record> + Send + 'static,
185    ///     impl Iterator<Item = &'static Record> + Send + 'static,
186    ///     impl Iterator<Item = &'static Record> + Send + 'static,
187    /// > {
188    ///     MessageResponseBuilder::from_message_request(request)
189    ///         .error_msg(&request.metadata, ResponseCode::ServFail)
190    /// }
191    /// ```
192    pub fn from_message_request(message: &'q MessageRequest) -> Self {
193        Self::new(&message.queries, None)
194    }
195
196    /// Associate EDNS with the Response
197    pub fn edns(&mut self, edns: &'q Edns) -> &mut Self {
198        self.edns = Some(edns);
199        self
200    }
201
202    /// Constructs the new MessageResponse with associated data
203    pub fn build<'a, A, N, S, D>(
204        self,
205        metadata: Metadata,
206        answers: A,
207        authorities: N,
208        soa: S,
209        additionals: D,
210    ) -> MessageResponse<'q, 'a, A::IntoIter, N::IntoIter, S::IntoIter, D::IntoIter>
211    where
212        A: IntoIterator<Item = &'a Record> + Send + 'a,
213        A::IntoIter: Send,
214        N: IntoIterator<Item = &'a Record> + Send + 'a,
215        N::IntoIter: Send,
216        S: IntoIterator<Item = &'a Record> + Send + 'a,
217        S::IntoIter: Send,
218        D: IntoIterator<Item = &'a Record> + Send + 'a,
219        D::IntoIter: Send,
220    {
221        MessageResponse {
222            metadata,
223            queries: self.queries,
224            answers: answers.into_iter(),
225            authorities: authorities.into_iter(),
226            soa: soa.into_iter(),
227            additionals: additionals.into_iter(),
228            signature: self.signature,
229            edns: self.edns,
230        }
231    }
232
233    /// Construct a Response with no associated records
234    pub fn build_no_records<'a>(
235        self,
236        metadata: Metadata,
237    ) -> MessageResponse<
238        'q,
239        'a,
240        impl Iterator<Item = &'a Record> + Send + 'a,
241        impl Iterator<Item = &'a Record> + Send + 'a,
242        impl Iterator<Item = &'a Record> + Send + 'a,
243        impl Iterator<Item = &'a Record> + Send + 'a,
244    > {
245        MessageResponse {
246            metadata,
247            queries: self.queries,
248            answers: Box::new(None.into_iter()),
249            authorities: Box::new(None.into_iter()),
250            soa: Box::new(None.into_iter()),
251            additionals: Box::new(None.into_iter()),
252            signature: self.signature,
253            edns: self.edns,
254        }
255    }
256
257    /// Constructs a new error MessageResponse with associated header and response code
258    pub fn error_msg<'a>(
259        self,
260        request_meta: &Metadata,
261        response_code: ResponseCode,
262    ) -> MessageResponse<
263        'q,
264        'a,
265        impl Iterator<Item = &'a Record> + Send + 'a,
266        impl Iterator<Item = &'a Record> + Send + 'a,
267        impl Iterator<Item = &'a Record> + Send + 'a,
268        impl Iterator<Item = &'a Record> + Send + 'a,
269    > {
270        let mut metadata = Metadata::response_from_request(request_meta);
271        metadata.response_code = response_code;
272
273        MessageResponse {
274            metadata,
275            queries: self.queries,
276            answers: Box::new(None.into_iter()),
277            authorities: Box::new(None.into_iter()),
278            soa: Box::new(None.into_iter()),
279            additionals: Box::new(None.into_iter()),
280            signature: self.signature,
281            edns: self.edns,
282        }
283    }
284}
285
286#[cfg(test)]
287mod tests {
288    use std::iter;
289    use std::net::Ipv4Addr;
290    use std::str::FromStr;
291
292    use crate::proto::op::{Header, Message, MessageType, Metadata, OpCode};
293    use crate::proto::rr::{DNSClass, Name, RData, Record};
294    use crate::proto::serialize::binary::{BinDecodable, BinDecoder, BinEncoder};
295
296    use super::*;
297
298    #[test]
299    fn test_truncation_ridiculous_number_answers() {
300        let mut buf = Vec::with_capacity(512);
301        {
302            let mut encoder = BinEncoder::new(&mut buf);
303            encoder.set_max_size(512);
304
305            let mut answer = Record::from_rdata(
306                Name::from_str("www.example.com.").unwrap(),
307                0,
308                RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
309            );
310            answer.dns_class = DNSClass::NONE;
311
312            let message = MessageResponse {
313                metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
314                queries: &Queries::empty(),
315                answers: iter::repeat(&answer),
316                authorities: iter::once(&answer),
317                soa: iter::once(&answer),
318                additionals: iter::once(&answer),
319                signature: None,
320                edns: None,
321            };
322
323            message
324                .destructive_emit(&mut encoder)
325                .expect("failed to encode");
326        }
327
328        let response = Message::from_vec(&buf).expect("failed to decode");
329        assert!(response.metadata.truncation);
330        assert!(response.answers.len() > 1);
331        // should never have written the authority section...
332        assert_eq!(response.authorities.len(), 0);
333    }
334
335    #[test]
336    fn test_truncation_ridiculous_number_nameservers() {
337        let mut buf = Vec::with_capacity(512);
338        {
339            let mut encoder = BinEncoder::new(&mut buf);
340            encoder.set_max_size(512);
341
342            let mut answer = Record::from_rdata(
343                Name::from_str("www.example.com.").unwrap(),
344                0,
345                RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
346            );
347            answer.dns_class = DNSClass::NONE;
348
349            let message = MessageResponse {
350                metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
351                queries: &Queries::empty(),
352                answers: iter::empty(),
353                authorities: iter::repeat(&answer),
354                soa: iter::repeat(&answer),
355                additionals: iter::repeat(&answer),
356                signature: None,
357                edns: None,
358            };
359
360            message
361                .destructive_emit(&mut encoder)
362                .expect("failed to encode");
363        }
364
365        let response = Message::from_vec(&buf).expect("failed to decode");
366        assert!(response.metadata.truncation);
367        assert_eq!(response.answers.len(), 0);
368        assert!(response.authorities.len() > 1);
369    }
370
371    // https://github.com/hickory-dns/hickory-dns/issues/2210
372    // If a client sends this DNS request to the hickory 0.24.0 DNS server:
373    //
374    // 08 00 00 00 00 01 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 00 00 00
375    // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
376    // 00 00
377    //
378    // i.e.:
379    // 08 00 ID
380    // 00 00 flags
381    // 00 01 QDCOUNT
382    // 00 00 ANCOUNT
383    // 00 00 NSCOUNT
384    // 00 00 ARCOUNT
385    // c0 00 QNAME
386    // 00 00 QTYPE
387    // 00 00 QCLASS
388    //
389    // hickory-dns fails the 2nd assert here while building the reply message
390    // (really while remembering names for pointers):
391    //
392    // pub fn slice_of(&self, start: usize, end: usize) -> &[u8] {
393    //     assert!(start < self.offset);
394    //     assert!(end <= self.buffer.len());
395    //     &self.buffer.buffer()[start..end]
396    // }
397    // The name is eight bytes long, but the current message size (after the
398    // current offset of 12) is only six, because QueriesEmitAndCount::emit()
399    // stored just the six bytes of the original encoded query:
400    //
401    //     encoder.emit_vec(self.cached_serialized)?;
402    #[test]
403    fn bad_length_of_named_pointers() {
404        let mut buf = Vec::with_capacity(512);
405        let mut encoder = BinEncoder::new(&mut buf);
406
407        let data: &[u8] = &[
408            0x08u8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
409            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412        ];
413
414        let mut decoder = BinDecoder::new(data);
415        let header = Header::read(&mut decoder).unwrap();
416        let msg = MessageRequest::read(&mut decoder, header).unwrap();
417
418        eprintln!("queries: {:?}", msg.queries.queries());
419
420        MessageResponseBuilder::new(&msg.queries, None)
421            .build_no_records(Metadata::response_from_request(&msg.metadata))
422            .destructive_emit(&mut encoder)
423            .unwrap();
424    }
425}