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::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, so the requestor advertised no buffer and RFC 1035 section 4.2.1
94                // restricts the message to 512 bytes
95                None => 512,
96            },
97            _ => u16::MAX,
98        });
99
100        let error = match self.destructive_emit(&mut encoder) {
101            Ok(info) => return Ok((info, bytes)),
102            Err(error) => error,
103        };
104
105        error!(%error, "error encoding message");
106        bytes.clear();
107        let mut encoder = BinEncoder::new(&mut bytes);
108        encoder.set_max_size(512);
109
110        let mut metadata = Metadata::new(id, MessageType::Response, OpCode::Query);
111        metadata.response_code = ResponseCode::ServFail;
112        let header = Header {
113            metadata,
114            counts: HeaderCounts::default(),
115        };
116
117        header.emit(&mut encoder)?;
118        Ok((ResponseInfo::from(header), bytes))
119    }
120
121    /// Consumes self, and emits to the encoder.
122    pub fn destructive_emit(
123        mut self,
124        encoder: &mut BinEncoder<'_>,
125    ) -> Result<ResponseInfo, ProtoError> {
126        // soa records are part of the authority section
127        let mut authorities = self.authorities.chain(self.soa);
128
129        let header = emit_message_parts(
130            &self.metadata,
131            &mut self.queries.as_emit_and_count(),
132            &mut self.answers,
133            &mut authorities,
134            &mut self.additionals,
135            self.edns,
136            self.signature.as_deref(),
137            encoder,
138        )?;
139
140        Ok(ResponseInfo::from(header))
141    }
142}
143
144/// A builder for MessageResponses
145pub struct MessageResponseBuilder<'q> {
146    queries: &'q Queries,
147    signature: Option<Box<Record<TSIG>>>,
148    edns: Option<&'q Edns>,
149}
150
151impl<'q> MessageResponseBuilder<'q> {
152    /// Constructs a new response builder
153    ///
154    /// # Arguments
155    ///
156    /// * `queries` - queries (from the Request) to associate with the Response
157    /// * `edns` - Optional Edns data to associate with the Response
158    pub fn new(queries: &'q Queries, edns: Option<&'q Edns>) -> Self {
159        MessageResponseBuilder {
160            queries,
161            signature: None,
162            edns,
163        }
164    }
165
166    /// Constructs a new response builder
167    ///
168    /// # Arguments
169    ///
170    /// * `message` - original request message to associate with the response
171    ///
172    /// # Example
173    ///
174    /// ```rust
175    /// use hickory_proto::{op::ResponseCode, rr::Record};
176    /// use hickory_server::{
177    ///     server::Request,
178    ///     zone_handler::{MessageResponse, MessageResponseBuilder},
179    /// };
180    ///
181    /// fn handle_request<'q>(request: &'q Request) -> MessageResponse<
182    ///     'q,
183    ///     '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    ///     impl Iterator<Item = &'static Record> + Send + 'static,
188    /// > {
189    ///     MessageResponseBuilder::from_message_request(request)
190    ///         .error_msg(&request.metadata, ResponseCode::ServFail)
191    /// }
192    /// ```
193    pub fn from_message_request(message: &'q MessageRequest) -> Self {
194        Self::new(&message.queries, None)
195    }
196
197    /// Associate EDNS with the Response
198    pub fn edns(&mut self, edns: &'q Edns) -> &mut Self {
199        self.edns = Some(edns);
200        self
201    }
202
203    /// Constructs the new MessageResponse with associated data
204    pub fn build<'a, A, N, S, D>(
205        self,
206        metadata: Metadata,
207        answers: A,
208        authorities: N,
209        soa: S,
210        additionals: D,
211    ) -> MessageResponse<'q, 'a, A::IntoIter, N::IntoIter, S::IntoIter, D::IntoIter>
212    where
213        A: IntoIterator<Item = &'a Record> + Send + 'a,
214        A::IntoIter: Send,
215        N: IntoIterator<Item = &'a Record> + Send + 'a,
216        N::IntoIter: Send,
217        S: IntoIterator<Item = &'a Record> + Send + 'a,
218        S::IntoIter: Send,
219        D: IntoIterator<Item = &'a Record> + Send + 'a,
220        D::IntoIter: Send,
221    {
222        MessageResponse {
223            metadata,
224            queries: self.queries,
225            answers: answers.into_iter(),
226            authorities: authorities.into_iter(),
227            soa: soa.into_iter(),
228            additionals: additionals.into_iter(),
229            signature: self.signature,
230            edns: self.edns,
231        }
232    }
233
234    /// Construct a Response with no associated records
235    pub fn build_no_records<'a>(
236        self,
237        metadata: Metadata,
238    ) -> MessageResponse<
239        'q,
240        '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        impl Iterator<Item = &'a Record> + Send + 'a,
245    > {
246        MessageResponse {
247            metadata,
248            queries: self.queries,
249            answers: Box::new(None.into_iter()),
250            authorities: Box::new(None.into_iter()),
251            soa: Box::new(None.into_iter()),
252            additionals: Box::new(None.into_iter()),
253            signature: self.signature,
254            edns: self.edns,
255        }
256    }
257
258    /// Constructs a new error MessageResponse with associated header and response code
259    pub fn error_msg<'a>(
260        self,
261        request_meta: &Metadata,
262        response_code: ResponseCode,
263    ) -> MessageResponse<
264        'q,
265        '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        impl Iterator<Item = &'a Record> + Send + 'a,
270    > {
271        let mut metadata = Metadata::response_from_request(request_meta);
272        metadata.response_code = response_code;
273
274        MessageResponse {
275            metadata,
276            queries: self.queries,
277            answers: Box::new(None.into_iter()),
278            authorities: Box::new(None.into_iter()),
279            soa: Box::new(None.into_iter()),
280            additionals: Box::new(None.into_iter()),
281            signature: self.signature,
282            edns: self.edns,
283        }
284    }
285}
286
287#[cfg(test)]
288mod tests {
289    use std::iter;
290    use std::net::Ipv4Addr;
291    use std::str::FromStr;
292
293    use crate::proto::op::{Header, Message, MessageType, Metadata, OpCode, Query};
294    use crate::proto::rr::{DNSClass, Name, RData, Record, RecordType};
295    use crate::proto::serialize::binary::{BinDecodable, BinDecoder, BinEncoder};
296
297    use super::*;
298
299    #[test]
300    fn test_truncation_ridiculous_number_answers() {
301        let mut buf = Vec::with_capacity(512);
302        {
303            let mut encoder = BinEncoder::new(&mut buf);
304            encoder.set_max_size(512);
305
306            let mut answer = Record::from_rdata(
307                Name::from_str("www.example.com.").unwrap(),
308                0,
309                RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
310            );
311            answer.dns_class = DNSClass::NONE;
312
313            let message = MessageResponse {
314                metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
315                queries: &Queries::empty(),
316                answers: iter::repeat(&answer),
317                authorities: iter::once(&answer),
318                soa: iter::once(&answer),
319                additionals: iter::once(&answer),
320                signature: None,
321                edns: None,
322            };
323
324            message
325                .destructive_emit(&mut encoder)
326                .expect("failed to encode");
327        }
328
329        let response = Message::from_vec(&buf).expect("failed to decode");
330        assert!(response.metadata.truncation);
331        assert!(response.answers.len() > 1);
332        // should never have written the authority section...
333        assert_eq!(response.authorities.len(), 0);
334    }
335
336    #[test]
337    fn test_truncation_ridiculous_number_nameservers() {
338        let mut buf = Vec::with_capacity(512);
339        {
340            let mut encoder = BinEncoder::new(&mut buf);
341            encoder.set_max_size(512);
342
343            let mut answer = Record::from_rdata(
344                Name::from_str("www.example.com.").unwrap(),
345                0,
346                RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
347            );
348            answer.dns_class = DNSClass::NONE;
349
350            let message = MessageResponse {
351                metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
352                queries: &Queries::empty(),
353                answers: iter::empty(),
354                authorities: iter::repeat(&answer),
355                soa: iter::repeat(&answer),
356                additionals: iter::repeat(&answer),
357                signature: None,
358                edns: None,
359            };
360
361            message
362                .destructive_emit(&mut encoder)
363                .expect("failed to encode");
364        }
365
366        let response = Message::from_vec(&buf).expect("failed to decode");
367        assert!(response.metadata.truncation);
368        assert_eq!(response.answers.len(), 0);
369        assert!(response.authorities.len() > 1);
370    }
371
372    /// A response with no OPT record answers a request that had none, so RFC 1035 section 4.2.1
373    /// applies and the message may not exceed 512 bytes.
374    #[test]
375    fn test_non_edns_udp_response_is_bounded_at_512() {
376        let answer = Record::from_rdata(
377            Name::from_str("www.example.com.").unwrap(),
378            0,
379            RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
380        );
381
382        let request = MessageRequest::mock(
383            Metadata::new(10, MessageType::Query, OpCode::Query),
384            Query::query(Name::root(), RecordType::A),
385        );
386        assert_eq!(request.max_payload(), 512);
387
388        let response = MessageResponseBuilder::from_message_request(&request).build(
389            Metadata::new(10, MessageType::Response, OpCode::Query),
390            iter::repeat(&answer),
391            [],
392            [],
393            [],
394        );
395
396        let (_info, buf) = response.encode(Protocol::Udp).expect("failed to encode");
397        assert!(buf.len() <= 512, "response was {} bytes", buf.len());
398
399        let response = Message::from_vec(&buf).expect("failed to decode");
400        assert!(response.metadata.truncation);
401        assert!(response.answers.len() > 1);
402    }
403
404    // https://github.com/hickory-dns/hickory-dns/issues/2210
405    // If a client sends this DNS request to the hickory 0.24.0 DNS server:
406    //
407    // 08 00 00 00 00 01 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 00 00 00
408    // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
409    // 00 00
410    //
411    // i.e.:
412    // 08 00 ID
413    // 00 00 flags
414    // 00 01 QDCOUNT
415    // 00 00 ANCOUNT
416    // 00 00 NSCOUNT
417    // 00 00 ARCOUNT
418    // c0 00 QNAME
419    // 00 00 QTYPE
420    // 00 00 QCLASS
421    //
422    // hickory-dns fails the 2nd assert here while building the reply message
423    // (really while remembering names for pointers):
424    //
425    // pub fn slice_of(&self, start: usize, end: usize) -> &[u8] {
426    //     assert!(start < self.offset);
427    //     assert!(end <= self.buffer.len());
428    //     &self.buffer.buffer()[start..end]
429    // }
430    // The name is eight bytes long, but the current message size (after the
431    // current offset of 12) is only six, because QueriesEmitAndCount::emit()
432    // stored just the six bytes of the original encoded query:
433    //
434    //     encoder.emit_vec(self.cached_serialized)?;
435    #[test]
436    fn bad_length_of_named_pointers() {
437        let mut buf = Vec::with_capacity(512);
438        let mut encoder = BinEncoder::new(&mut buf);
439
440        let data: &[u8] = &[
441            0x08u8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
442            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445        ];
446
447        let mut decoder = BinDecoder::new(data);
448        let header = Header::read(&mut decoder).unwrap();
449        let msg = MessageRequest::read(&mut decoder, header).unwrap();
450
451        eprintln!("queries: {:?}", msg.queries.queries());
452
453        MessageResponseBuilder::new(&msg.queries, None)
454            .build_no_records(Metadata::response_from_request(&msg.metadata))
455            .destructive_emit(&mut encoder)
456            .unwrap();
457    }
458}