step (SIG)

This commit is contained in:
Stefan Bühler 2018-02-11 11:13:04 +01:00
parent 0261d27764
commit adb00b77b6
6 changed files with 133 additions and 7 deletions

View File

@ -6,6 +6,7 @@ pub mod types;
mod eui; mod eui;
mod nsec; mod nsec;
mod nxt; mod nxt;
mod sig;
mod time; mod time;
mod uri; mod uri;
@ -15,7 +16,8 @@ pub use self::eui::{EUI48Addr, EUI64Addr};
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName}; pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName}; pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName};
pub use self::nxt::NxtTypeBitmap; pub use self::nxt::NxtTypeBitmap;
pub use self::sig::OptionalTTL;
pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText}; pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText};
pub use self::time::{Time, Time48}; pub use self::time::{Time, TimeStrict, Time48};
pub use self::types::Type; pub use self::types::Type;
pub use self::uri::UriText; pub use self::uri::UriText;

View File

@ -78,7 +78,7 @@ pub fn deserialize_name(data: &mut Cursor<Bytes>, accept_compressed: bool) -> Re
total_len += 1 + label_len; total_len += 1 + label_len;
// max len 255, but there also needs to be an empty label at the end // max len 255, but there also needs to be an empty label at the end
if total_len > 254 { bail!{"DNS name too long"} } if total_len > 254 { bail!{"DNS name too long"} }
check_enough_data!(data, (label_len), "DnsName label"); check_enough_data!(data, label_len, "DnsName label");
data.advance(label_len); data.advance(label_len);
} }
} }

View File

@ -0,0 +1,52 @@
use bytes::Bytes;
use errors::*;
use failure::Fail;
use ser::packet::{DnsPacketData, DnsPacketWriteContext};
use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field};
use std::fmt;
use std::io::Cursor;
/// Optional TTL
///
/// Always present in wire format, but optional in zone; defaults to TTL
/// of the RR.
///
/// Must be followed by a field that doesn't accept any unsigned 32-bit
/// integer as text representation (like `TimeStrict` for `SIG`).
///
/// If field is missing in zone representation the context must provide
/// a TTL.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct OptionalTTL(pub u32);
impl DnsPacketData for OptionalTTL {
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
Ok(OptionalTTL(DnsPacketData::deserialize(data)?))
}
fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec<u8>) -> Result<()> {
self.0.serialize(context, packet)
}
}
impl DnsTextData for OptionalTTL {
fn dns_parse(context: &DnsTextContext, data: &mut &str) -> ::errors::Result<Self> {
let mut data_found = *data;
let field = next_field(&mut data_found)?;
match field.parse::<u32>() {
Ok(ttl) => {
*data = data_found;
Ok(OptionalTTL(ttl))
},
Err(e) => {
Ok(OptionalTTL(context.last_ttl()
.ok_or_else(|| e.context("TTL not available in context, failed parsing optional TTL"))?
))
},
}
}
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
self.0.dns_format(f)
}
}

View File

@ -7,9 +7,12 @@ use std::io::Cursor;
mod epoch; mod epoch;
/// timestamp in seconds since epoch (ignoring leap seconds) /// Timestamp in seconds since epoch (ignoring leap seconds)
/// ///
/// Is expected to wrap around. /// Is expected to wrap around.
///
/// Accepts both YYYYMMDDHHmmSS or an unsigned 32-bit integer in text
/// form; formatted as YYYYMMDDHHmmSS for now.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct Time(pub u32); pub struct Time(pub u32);
@ -37,7 +40,36 @@ impl DnsTextData for Time {
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
epoch::Tm::from_epoch(self.0 as i64).unwrap().format_YYYYMMDDHHmmSS(&mut*f.format_field()?) epoch::Tm::from_epoch(self.0 as i64).unwrap().format_YYYYMMDDHHmmSS(&mut*f.format_field()?)
// write!(f, "{}", self.0) }
}
/// Timestamp in seconds since epoch (ignoring leap seconds)
///
/// Is expected to wrap around.
///
/// Accepts only YYYYMMDDHHmmSS.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TimeStrict(pub u32);
impl DnsPacketData for TimeStrict {
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
Ok(TimeStrict(DnsPacketData::deserialize(data)?))
}
fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec<u8>) -> Result<()> {
self.0.serialize(context, packet)
}
}
impl DnsTextData for TimeStrict {
fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> ::errors::Result<Self> {
let field = next_field(data)?;
let tm = epoch::Tm::parse_YYYYMMDDHHmmSS(field)?;
Ok(TimeStrict(tm.epoch() as u32))
}
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
epoch::Tm::from_epoch(self.0 as i64).unwrap().format_YYYYMMDDHHmmSS(&mut*f.format_field()?)
} }
} }

View File

@ -80,6 +80,11 @@ fn serialized_answer(rrdata: Box<RRData>) -> Result<Bytes> {
fn check(q: Type, text_input: &'static str, canonic: Option<&'static str>, raw: &'static [u8]) { fn check(q: Type, text_input: &'static str, canonic: Option<&'static str>, raw: &'static [u8]) {
// Make sure the canonic representation is sound itself
if let Some(canonic) = canonic {
check(q, canonic, None, raw);
}
let canonic = canonic.unwrap_or(text_input); let canonic = canonic.unwrap_or(text_input);
let mut context = text::DnsTextContext::new(); let mut context = text::DnsTextContext::new();
@ -144,6 +149,9 @@ fn test_NS() {
); );
} }
// missing test_MD
// missing test_MF
#[test] #[test]
fn test_CNAME() { fn test_CNAME() {
// local alias // local alias
@ -200,6 +208,9 @@ fn test_SOA() {
); );
} }
// missing test_MB
// missing test_MG
#[test] #[test]
fn test_MR() { fn test_MR() {
// BROKEN TESTS (2) (deprecated) // BROKEN TESTS (2) (deprecated)
@ -257,6 +268,8 @@ fn test_HINFO() {
); );
} }
// missing test_MINFO
#[test] #[test]
fn test_MX() { fn test_MX() {
// local name // local name
@ -348,6 +361,20 @@ fn test_AFSDB() {
); );
} }
// missing test_RT
// missing test_NSAP_PTR
#[test]
fn test_SIG() {
// not supported by powerdns
// last ttl is 3600 in this test environment
check(types::SIG,
"NXT 1 2 19970102030405 19961211100908 2143 foo.nil. AIYADP8d3zYNyQwW2EM4wXVFdslEJcUx/fxkfBeH1El4ixPFhpfHFElxbvKoWmvjDTCm fiYy2X+8XpFjwICHc398kzWsTMKlxovpz2FnCTM=",
Some("NXT 1 2 3600 19970102030405 19961211100908 2143 foo.nil. AIYADP8d3zYNyQwW2EM4wXVFdslEJcUx/fxkfBeH1El4ixPFhpfHFElxbvKoWmvjDTCmfiYy2X+8XpFjwICHc398kzWsTMKlxovpz2FnCTM="),
b"\x00\x1e\x01\x02\x00\x00\x0e\x10\x32\xcb\x25\xa5\x32\xae\x88\x44\x08\x5f\x03foo\x03nil\x00\x00\x86\x00\x0c\xff\x1d\xdf\x36\x0d\xc9\x0c\x16\xd8\x43\x38\xc1\x75\x45\x76\xc9\x44\x25\xc5\x31\xfd\xfc\x64\x7c\x17\x87\xd4\x49\x78\x8b\x13\xc5\x86\x97\xc7\x14\x49\x71\x6e\xf2\xa8\x5a\x6b\xe3\x0d\x30\xa6\x7e\x26\x32\xd9\x7f\xbc\x5e\x91\x63\xc0\x80\x87\x73\x7f\x7c\x93\x35\xac\x4c\xc2\xa5\xc6\x8b\xe9\xcf\x61\x67\x09\x33"
);
}
#[test] #[test]
fn test_KEY() { fn test_KEY() {
// deprecated (and i don't know what i am doing wrong) // deprecated (and i don't know what i am doing wrong)
@ -358,6 +385,9 @@ fn test_KEY() {
); );
} }
// missing test_PX
// missing test_GPOS
#[test] #[test]
fn test_AAAA() { fn test_AAAA() {
check(types::AAAA, check(types::AAAA,
@ -401,6 +431,8 @@ fn test_LOC() {
); );
} }
// missing test_NXT
#[test] #[test]
fn test_SRV() { fn test_SRV() {
// local name // local name
@ -456,6 +488,9 @@ fn test_CERT() {
); );
} }
// missing test_A6
// missing test_DNAME
#[test] #[test]
fn test_DS() { fn test_DS() {
check(types::DS, check(types::DS,
@ -700,6 +735,11 @@ fn test_SMIMEA() {
); );
} }
// missing test_NINFO
// missing test_RKEY
// missing test_CDS
// missing test_CDNSKEY
#[test] #[test]
fn test_OPENPGPKEY() { fn test_OPENPGPKEY() {
check(types::OPENPGPKEY, check(types::OPENPGPKEY,

View File

@ -182,9 +182,9 @@ pub struct SIG {
// RFC says this can be omitted in text form if it is the same as // RFC says this can be omitted in text form if it is the same as
// the TTL on the SIG record. not supported to be omitted here // the TTL on the SIG record. not supported to be omitted here
// (TODO?). // (TODO?).
original_ttl: u32, original_ttl: OptionalTTL,
signature_expiration: u32, signature_expiration: TimeStrict,
signature_inception: u32, signature_inception: TimeStrict,
key_tag: u16, key_tag: u16,
signers_name: DnsCanonicalName, signers_name: DnsCanonicalName,
signature: Base64RemainingBlob, signature: Base64RemainingBlob,