hickory_client/client/
dnssec_client.rs

1// Copyright 2015-2019 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 std::future::Future;
9use std::pin::Pin;
10use std::sync::Arc;
11
12use futures_util::stream::Stream;
13
14use crate::client::Client;
15use crate::proto::ProtoError;
16use crate::proto::dnssec::DnssecDnsHandle;
17use crate::proto::dnssec::TrustAnchors;
18use crate::proto::runtime::TokioTime;
19use crate::proto::xfer::{
20    DnsExchangeBackground, DnsHandle, DnsRequest, DnsRequestSender, DnsResponse,
21};
22
23/// A DNSSEC Client implemented over futures-rs.
24///
25/// This Client is generic and capable of wrapping UDP, TCP, and other underlying DNS protocol
26///  implementations.
27pub struct DnssecClient {
28    client: DnssecDnsHandle<Client>,
29}
30
31impl DnssecClient {
32    /// Returns a DNSSEC verifying client with a TrustAnchor that can be replaced
33    pub fn builder<F, S>(connect_future: F) -> AsyncSecureClientBuilder<F, S>
34    where
35        F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
36        S: DnsRequestSender + 'static,
37    {
38        AsyncSecureClientBuilder {
39            connect_future,
40            trust_anchor: None,
41        }
42    }
43
44    /// Returns a DNSSEC verifying client with the default TrustAnchor
45    pub async fn connect<F, S>(
46        connect_future: F,
47    ) -> Result<(Self, DnsExchangeBackground<S, TokioTime>), ProtoError>
48    where
49        S: DnsRequestSender,
50        F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
51    {
52        Self::builder(connect_future).build().await
53    }
54
55    fn from_client(client: Client, trust_anchor: Arc<TrustAnchors>) -> Self {
56        Self {
57            client: DnssecDnsHandle::with_trust_anchor(client, trust_anchor),
58        }
59    }
60}
61
62impl Clone for DnssecClient {
63    fn clone(&self) -> Self {
64        Self {
65            client: self.client.clone(),
66        }
67    }
68}
69
70impl DnsHandle for DnssecClient {
71    type Response = Pin<Box<(dyn Stream<Item = Result<DnsResponse, ProtoError>> + Send + 'static)>>;
72
73    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&self, request: R) -> Self::Response {
74        self.client.send(request)
75    }
76}
77
78/// A builder to allow a custom trust to be used for validating all signed records
79pub struct AsyncSecureClientBuilder<F, S>
80where
81    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
82    S: DnsRequestSender + 'static,
83{
84    connect_future: F,
85    trust_anchor: Option<TrustAnchors>,
86}
87
88impl<F, S> AsyncSecureClientBuilder<F, S>
89where
90    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
91    S: DnsRequestSender + 'static,
92{
93    /// This variant allows for the trust_anchor to be replaced
94    ///
95    /// # Arguments
96    ///
97    /// * `trust_anchor` - the set of trusted DNSKEY public_keys, by default this only contains the
98    ///   root public_key.
99    pub fn trust_anchor(mut self, trust_anchor: TrustAnchors) -> Self {
100        self.trust_anchor = Some(trust_anchor);
101        self
102    }
103
104    /// Construct the new client
105    pub async fn build(
106        mut self,
107    ) -> Result<(DnssecClient, DnsExchangeBackground<S, TokioTime>), ProtoError> {
108        let trust_anchor = Arc::new(self.trust_anchor.take().unwrap_or_default());
109        let result = Client::connect(self.connect_future).await;
110
111        result.map(|(client, bg)| (DnssecClient::from_client(client, trust_anchor), bg))
112    }
113}