103 lines
3.6 KiB
Go
103 lines
3.6 KiB
Go
package checker
|
|
|
|
import "time"
|
|
|
|
const ObservationKeyDNSSEC = "dnssec"
|
|
|
|
// DenialKind describes the negative-answer scheme observed on a NXDOMAIN probe.
|
|
type DenialKind string
|
|
|
|
const (
|
|
DenialNone DenialKind = "NONE" // zone unsigned or no NSEC/NSEC3 records returned
|
|
DenialNSEC DenialKind = "NSEC" // walkable
|
|
DenialNSEC3 DenialKind = "NSEC3" // hashed denial of existence
|
|
DenialOptOut DenialKind = "OPT-OUT" // NSEC3 with the OPT-OUT flag set
|
|
)
|
|
|
|
// DNSSECData carries raw facts only; judgement is delegated to the rules.
|
|
type DNSSECData struct {
|
|
Domain string `json:"domain"`
|
|
NameServers []string `json:"name_servers,omitempty"`
|
|
Servers map[string]PerServerView `json:"servers,omitempty"` // key: "host:port"
|
|
Errors []string `json:"errors,omitempty"` // global errors (NS resolution, …)
|
|
CollectedAt time.Time `json:"collected_at"`
|
|
|
|
// HasDS is whether the parent advertises a DS for this zone (best effort,
|
|
// resolved through the bootstrap resolver). Used by dnssec_zone_signed.
|
|
HasDS bool `json:"has_ds,omitempty"`
|
|
}
|
|
|
|
type PerServerView struct {
|
|
Server string `json:"server"`
|
|
UDPError string `json:"udp_error,omitempty"`
|
|
TCPError string `json:"tcp_error,omitempty"`
|
|
|
|
DNSKEYs []DNSKEYRecord `json:"dnskeys,omitempty"`
|
|
DNSKEYTTL uint32 `json:"dnskey_ttl,omitempty"`
|
|
DNSKEYRRSIGs []RRSIGObservation `json:"dnskey_rrsigs,omitempty"`
|
|
|
|
SOA *SOAObservation `json:"soa,omitempty"`
|
|
SOARRSIGs []RRSIGObservation `json:"soa_rrsigs,omitempty"`
|
|
|
|
NSEC3PARAM *NSEC3ParamObservation `json:"nsec3param,omitempty"`
|
|
|
|
DenialKind DenialKind `json:"denial_kind,omitempty"`
|
|
DenialRecords []string `json:"denial_records,omitempty"` // textual dump for the report
|
|
ProbeName string `json:"probe_name,omitempty"` // random NXDOMAIN probe used
|
|
|
|
CDS []DSRecord `json:"cds,omitempty"`
|
|
CDNSKEY []DNSKEYRecord `json:"cdnskey,omitempty"`
|
|
}
|
|
|
|
// AllRRSIGs returns DNSKEY and SOA RRSIGs concatenated into a fresh slice, so
|
|
// callers can iterate every signature observed on this server without mutating
|
|
// the underlying fields.
|
|
func (v *PerServerView) AllRRSIGs() []RRSIGObservation {
|
|
out := make([]RRSIGObservation, 0, len(v.DNSKEYRRSIGs)+len(v.SOARRSIGs))
|
|
out = append(out, v.DNSKEYRRSIGs...)
|
|
out = append(out, v.SOARRSIGs...)
|
|
return out
|
|
}
|
|
|
|
type DNSKEYRecord struct {
|
|
Flags uint16 `json:"flags"`
|
|
Protocol uint8 `json:"protocol"`
|
|
Algorithm uint8 `json:"algorithm"`
|
|
PublicKey string `json:"public_key"`
|
|
KeyTag uint16 `json:"keytag"`
|
|
KeySize int `json:"key_size,omitempty"` // computed at collect time
|
|
IsKSK bool `json:"is_ksk,omitempty"` // derived from the SEP flag
|
|
}
|
|
|
|
type RRSIGObservation struct {
|
|
TypeCovered uint16 `json:"type_covered"`
|
|
Algorithm uint8 `json:"algorithm"`
|
|
Labels uint8 `json:"labels"`
|
|
OrigTTL uint32 `json:"orig_ttl"`
|
|
Inception uint32 `json:"inception"`
|
|
Expiration uint32 `json:"expiration"`
|
|
KeyTag uint16 `json:"keytag"`
|
|
SignerName string `json:"signer_name"`
|
|
}
|
|
|
|
type SOAObservation struct {
|
|
Serial uint32 `json:"serial"`
|
|
Minimum uint32 `json:"minimum"`
|
|
MName string `json:"mname"`
|
|
TTL uint32 `json:"ttl"`
|
|
}
|
|
|
|
type NSEC3ParamObservation struct {
|
|
HashAlgorithm uint8 `json:"hash_algorithm"`
|
|
Flags uint8 `json:"flags"` // OPT-OUT bit = 0x01
|
|
Iterations uint16 `json:"iterations"`
|
|
SaltLength uint8 `json:"salt_length"`
|
|
Salt string `json:"salt,omitempty"` // hex
|
|
}
|
|
|
|
type DSRecord struct {
|
|
KeyTag uint16 `json:"keytag"`
|
|
Algorithm uint8 `json:"algorithm"`
|
|
DigestType uint8 `json:"digest_type"`
|
|
Digest string `json:"digest"`
|
|
}
|