Skip to main content

toluol_proto/rdata/
sshfp.rs

1//! `SSHFP` RDATA definition.
2
3use std::fmt::Display;
4use std::io::{Read, Write};
5
6use byteorder::{ReadBytesExt, WriteBytesExt};
7use data_encoding::HEXUPPER;
8use repr_with_fallback::repr_with_fallback;
9
10use crate::error::{EncodeError, ParseError};
11
12use super::{Rdata, RdataTrait};
13
14#[cfg(feature = "serde")]
15use serde::Serialize;
16
17repr_with_fallback! {
18    /// The public key algorithms for [`SSHFP`] records.
19    /// [\[RFC 4255\]](https://www.rfc-editor.org/rfc/rfc4255)
20    ///
21    /// See <https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml> for
22    /// the official list.
23    #[cfg_attr(feature = "serde", derive(Serialize))]
24    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
25    #[non_exhaustive]
26    pub enum Algorithm {
27        RSA = 1,
28        DSA = 2,
29        ECDSA = 3,
30        ED25519 = 4,
31        ED448 = 6,
32        Unassigned(u8), // 0, 5, 7-255 (technically, 0 is Reserved, but we treat it as Unassigned)
33    }
34}
35
36repr_with_fallback! {
37    /// The message-digest algorithms for fingerprints in [`SSHFP`] records.
38    /// [\[RFC 4255\]](https://www.rfc-editor.org/rfc/rfc4255)
39    ///
40    /// See <https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml> for
41    /// the official list.
42    #[cfg_attr(feature = "serde", derive(Serialize))]
43    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
44    #[non_exhaustive]
45    pub enum FingerprintType {
46        SHA1 = 1,
47        SHA256 = 2,
48        Unassigned(u8), // 0, 3-255 (technically, 0 is Reserved, but we treat it as Unassigned)
49    }
50}
51
52/// A record containg a fingerprint of an SSH public host key that is associated with a DNS name.
53/// [\[RFC 4255\]](https://www.rfc-editor.org/rfc/rfc4255)
54#[cfg_attr(feature = "serde", derive(Serialize))]
55#[derive(PartialEq, Eq, Clone, Debug)]
56pub struct SSHFP {
57    /// The algorithm of the public key.
58    pub algorithm: Algorithm,
59    /// The message-digest algorithm used to calculate the fingerprint of the public key.
60    pub fingerprint_type: FingerprintType,
61    /// The fingerprint, calculated over the public key blob as described in
62    /// [RFC 4253](https://www.rfc-editor.org/rfc/rfc4253).
63    pub fingerprint: Vec<u8>,
64}
65
66impl RdataTrait for SSHFP {
67    fn parse_rdata(rdata: &mut std::io::Cursor<&[u8]>, rdlength: u16) -> Result<Rdata, ParseError> {
68        let algorithm: Algorithm = rdata.read_u8()?.into();
69        let fingerprint_type: FingerprintType = rdata.read_u8()?.into();
70        // we already read: u8 (2) + u8 (1) = 2 bytes
71        let mut fingerprint = vec![0; (rdlength - 2) as usize];
72        rdata.read_exact(&mut fingerprint)?;
73
74        Ok(Rdata::SSHFP(Self {
75            algorithm,
76            fingerprint_type,
77            fingerprint,
78        }))
79    }
80
81    fn encode_rdata_into(&self, buf: &mut impl Write) -> Result<u16, EncodeError> {
82        buf.write_u8(self.algorithm.into())?;
83        buf.write_u8(self.fingerprint_type.into())?;
84        buf.write_all(&self.fingerprint)?;
85
86        Ok(self.fingerprint.len() as u16 + 1 + 1)
87    }
88}
89
90impl Display for SSHFP {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        let algorithm: u8 = self.algorithm.into();
93        let fingerprint_type: u8 = self.fingerprint_type.into();
94        let fingerprint = HEXUPPER.encode(&self.fingerprint);
95        write!(f, "{} {} {}", algorithm, fingerprint_type, fingerprint)
96    }
97}