-
Notifications
You must be signed in to change notification settings - Fork 1
/
dnskey.go
100 lines (87 loc) · 2.75 KB
/
dnskey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package main
import (
"errors"
"fmt"
"github.com/miekg/dns"
"github.com/apex/log"
)
func checkDNSKEY(cache Cache, origin string) (r Result) {
if _, ok := cache[origin]["DNSKEY"]; !ok {
log.Errorf("No DNSKEY records at apex of %s", origin)
r.errors++
return
}
// keys of same alg must have different keytag
var keytags map[string]bool = make(map[string]bool)
for _, k := range cache[origin]["DNSKEY"] {
var key *dns.DNSKEY = k.(*dns.DNSKEY)
alg_keytag := fmt.Sprintf("%d+%d", key.Algorithm, key.KeyTag())
if _, ok := keytags[alg_keytag]; ok {
log.Warnf("DNSKEY RRset contains two keys of algorithm %s (%d) with KeyTag %d\n", algorithm2string(key.Algorithm), key.Algorithm, key.KeyTag())
r.warnings++
}
keytags[alg_keytag] = true
}
// at least one key of each algorithm should have the SEP flag set
var algSEP map[uint8]bool = make(map[uint8]bool)
for _, k := range cache[origin]["DNSKEY"] {
var key *dns.DNSKEY = k.(*dns.DNSKEY)
if _, ok := algSEP[key.Algorithm]; !ok {
algSEP[key.Algorithm] = false
}
if key.Flags&dns.SEP == dns.SEP {
algSEP[key.Algorithm] = true
}
}
for alg := range algSEP {
if !algSEP[alg] {
log.Warnf("No DNSKEY of algorithm %s (%d) has SEP flag set\n", algorithm2string(alg), alg)
r.warnings++
}
}
// only allows algorithms used
for _, k := range cache[origin]["DNSKEY"] {
var key *dns.DNSKEY = k.(*dns.DNSKEY)
if !okAlgorithm(key.Algorithm) {
log.Warnf("DNSKEY with algorithm %s (%d) found\n", algorithm2string(key.Algorithm), key.Algorithm)
r.warnings++
}
}
// check that all keys with SEP flag set sign the DNSKEY set
for _, k := range cache[origin]["DNSKEY"] {
var key *dns.DNSKEY = k.(*dns.DNSKEY)
if key.Flags&dns.SEP != dns.SEP {
continue
}
// SEP is set, key must sign DNSKEY set
signs, err := keySigns(key, cache[origin]["DNSKEY"], cache[origin]["RRSIGDNSKEY"])
if err != nil {
log.Error(err.Error())
r.errors++
} else if !signs {
log.Warnf("DNSKEY algorithm %s (%d) keyTag %d, has SEP flag set, but doesn ot sign the DNSKEY set.\n", algorithm2string(key.Algorithm), key.Algorithm, key.KeyTag())
r.warnings++
}
}
// done
return
}
func keySigns(key *dns.DNSKEY, rrset []dns.RR, rrsigs []dns.RR) (bool, error) {
if !dns.IsRRset(rrset) {
return false, errors.New("Second parameter is not a RR set.")
}
if !dns.IsRRset(rrsigs) || rrsigs[0].Header().Rrtype != dns.TypeRRSIG {
return false, errors.New("Third parameter is not a RRSIG set.")
}
if rrsigs[0].(*dns.RRSIG).TypeCovered != rrset[0].Header().Rrtype {
return false, errors.New("RRSIG set does not cover RR set.")
}
// now check the signature
for _, rrsig := range rrsigs {
err := rrsig.(*dns.RRSIG).Verify(key, rrset)
if err == nil {
return true, nil
}
}
return false, nil
}