///|
pub struct Rrsig {
priv covered : Int32
priv algorithm : Int32
priv labels : Int32
priv original_ttl : UInt32
priv expiration : UInt32
priv inception : UInt32
priv key_tag : Int32
priv signer : Name
priv signature : Bytes
} derive(Eq, Debug)
///|
pub extend Rrsig with Eq::{equal, not_equal}
///|
pub extend Rrsig with @debug.Debug::{to_repr}
///|
pub fn Rrsig::parse(data : Bytes) -> Result[Rrsig, DnsError] {
if data.length() < 20 || data.length() > 16384 {
return Err(Malformed("RRSIG size outside supported bounds"))
}
let (signer, end) = match read_name(data, 18) {
Ok(x) => x
Err(e) => return Err(e)
}
if end == data.length() {
return Err(Malformed("empty RRSIG signature"))
}
Ok({
covered: u16_at(data, 0),
algorithm: data[2].to_int(),
labels: data[3].to_int(),
original_ttl: u32_at(data, 4),
expiration: u32_at(data, 8),
inception: u32_at(data, 12),
key_tag: u16_at(data, 16),
signer,
signature: data[end:].to_owned(),
})
}
///|
pub fn Rrsig::signer(self : Rrsig) -> Name {
self.signer
}
///|
pub fn Rrsig::covered_type(self : Rrsig) -> Int32 {
self.covered
}
///|
/// RFC1982 arithmetic: validity intervals must be less than half the serial space.
pub fn Rrsig::remaining(
self : Rrsig,
time : TimePolicy,
) -> Result[UInt32, DnsError] {
match time.validate() {
Err(e) => return Err(e)
Ok(_) => ()
}
let span = self.expiration - self.inception
if span >= 0x80000000U {
return Err(Bogus("ambiguous RRSIG validity interval"))
}
let elapsed = time.now - self.inception
if elapsed <= span {
return Ok(span - elapsed)
}
let until_start = self.inception - time.now
if until_start <= time.skew {
return Ok(span)
}
let since_end = time.now - self.expiration
if since_end <= time.skew {
return Ok(0U)
}
Err(Stale("RRSIG outside validity interval"))
}
///|
fn Rrsig::preamble(self : Rrsig) -> Bytes {
let out : Array[Byte] = []
append16(out, self.covered)
out.push(self.algorithm.to_byte())
out.push(self.labels.to_byte())
append32(out, self.original_ttl)
append32(out, self.expiration)
append32(out, self.inception)
append16(out, self.key_tag)
append_bytes(out, self.signer.wire())
Bytes::from_array(out)
}
///|
pub fn Rrsig::rdata(self : Rrsig) -> Bytes {
let out : Array[Byte] = []
append_bytes(out, self.preamble())
append_bytes(out, self.signature)
Bytes::from_array(out)
}
///|
fn u32_at(data : Bytes, p : Int32) -> UInt32 {
(data[p].to_uint() << 24) |
(data[p + 1].to_uint() << 16) |
(data[p + 2].to_uint() << 8) |
data[p + 3].to_uint()
}
///|
fn append32(out : Array[Byte], n : UInt32) -> Unit {
out.push((n >> 24).to_byte())
out.push((n >> 16).to_byte())
out.push((n >> 8).to_byte())
out.push(n.to_byte())
}