aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/dnssec/dnskey.go21
-rw-r--r--plugin/dnssec/dnssec.go20
-rw-r--r--plugin/dnssec/dnssec_test.go40
-rw-r--r--plugin/dnssec/responsewriter.go3
-rw-r--r--plugin/dnssec/rrsig.go2
-rw-r--r--plugin/dnssec/setup.go4
6 files changed, 57 insertions, 33 deletions
diff --git a/plugin/dnssec/dnskey.go b/plugin/dnssec/dnskey.go
index ce787ab54..885538fbf 100644
--- a/plugin/dnssec/dnskey.go
+++ b/plugin/dnssec/dnskey.go
@@ -15,9 +15,10 @@ import (
// DNSKEY holds a DNSSEC public and private key used for on-the-fly signing.
type DNSKEY struct {
- K *dns.DNSKEY
- s crypto.Signer
- keytag uint16
+ K *dns.DNSKEY
+ D *dns.DS
+ s crypto.Signer
+ tag uint16
}
// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other
@@ -36,18 +37,20 @@ func ParseKeyFile(pubFile, privFile string) (*DNSKEY, error) {
if e != nil {
return nil, e
}
- p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, privFile)
+
+ dk := k.(*dns.DNSKEY)
+ p, e := dk.ReadPrivateKey(f, privFile)
if e != nil {
return nil, e
}
- if v, ok := p.(*rsa.PrivateKey); ok {
- return &DNSKEY{k.(*dns.DNSKEY), v, k.(*dns.DNSKEY).KeyTag()}, nil
+ if s, ok := p.(*rsa.PrivateKey); ok {
+ return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: s, tag: dk.KeyTag()}, nil
}
- if v, ok := p.(*ecdsa.PrivateKey); ok {
- return &DNSKEY{k.(*dns.DNSKEY), v, k.(*dns.DNSKEY).KeyTag()}, nil
+ if s, ok := p.(*ecdsa.PrivateKey); ok {
+ return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: s, tag: dk.KeyTag()}, nil
}
- return &DNSKEY{k.(*dns.DNSKEY), nil, 0}, errors.New("no known? private key found")
+ return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: nil, tag: 0}, errors.New("no known private key found")
}
// getDNSKEY returns the correct DNSKEY to the client. Signatures are added when do is true.
diff --git a/plugin/dnssec/dnssec.go b/plugin/dnssec/dnssec.go
index 9a20776fe..b4f738691 100644
--- a/plugin/dnssec/dnssec.go
+++ b/plugin/dnssec/dnssec.go
@@ -35,20 +35,30 @@ func New(zones []string, keys []*DNSKEY, next plugin.Handler, c *cache.Cache) Dn
}
// Sign signs the message in state. it takes care of negative or nodata responses. It
-// uses NSEC black lies for authenticated denial of existence. Signatures
-// creates will be cached for a short while. By default we sign for 8 days,
+// uses NSEC black lies for authenticated denial of existence. For delegations it
+// will insert DS records and sign those.
+// Signatures will be cached for a short while. By default we sign for 8 days,
// starting 3 hours ago.
func (d Dnssec) Sign(state request.Request, zone string, now time.Time) *dns.Msg {
req := state.Req
+ incep, expir := incepExpir(now)
+
mt, _ := response.Typify(req, time.Now().UTC()) // TODO(miek): need opt record here?
if mt == response.Delegation {
- // TODO(miek): uh, signing DS record?!?!
+ ttl := req.Ns[0].Header().Ttl
+
+ ds := []dns.RR{}
+ for i := range d.keys {
+ ds = append(ds, d.keys[i].D)
+ }
+ if sigs, err := d.sign(ds, zone, ttl, incep, expir); err == nil {
+ req.Ns = append(req.Ns, ds...)
+ req.Ns = append(req.Ns, sigs...)
+ }
return req
}
- incep, expir := incepExpir(now)
-
if mt == response.NameError || mt == response.NoData {
if req.Ns[0].Header().Rrtype != dns.TypeSOA || len(req.Ns) > 1 {
return req
diff --git a/plugin/dnssec/dnssec_test.go b/plugin/dnssec/dnssec_test.go
index 34c9bf331..ab41800a1 100644
--- a/plugin/dnssec/dnssec_test.go
+++ b/plugin/dnssec/dnssec_test.go
@@ -21,10 +21,10 @@ func TestZoneSigning(t *testing.T) {
m = d.Sign(state, "miek.nl.", time.Now().UTC())
if !section(m.Answer, 1) {
- t.Errorf("answer section should have 1 sig")
+ t.Errorf("Answer section should have 1 RRSIG")
}
if !section(m.Ns, 1) {
- t.Errorf("authority section should have 1 sig")
+ t.Errorf("Authority section should have 1 RRSIG")
}
}
@@ -40,7 +40,7 @@ func TestZoneSigningDouble(t *testing.T) {
key1, err := ParseKeyFile(fPub1, fPriv1)
if err != nil {
- t.Fatalf("failed to parse key: %v\n", err)
+ t.Fatalf("Failed to parse key: %v\n", err)
}
d.keys = append(d.keys, key1)
@@ -48,10 +48,10 @@ func TestZoneSigningDouble(t *testing.T) {
state := request.Request{Req: m}
m = d.Sign(state, "miek.nl.", time.Now().UTC())
if !section(m.Answer, 2) {
- t.Errorf("answer section should have 1 sig")
+ t.Errorf("Answer section should have 1 RRSIG")
}
if !section(m.Ns, 2) {
- t.Errorf("authority section should have 1 sig")
+ t.Errorf("Authority section should have 1 RRSIG")
}
}
@@ -64,7 +64,7 @@ func TestSigningDifferentZone(t *testing.T) {
key, err := ParseKeyFile(fPub, fPriv)
if err != nil {
- t.Fatalf("failed to parse key: %v\n", err)
+ t.Fatalf("Failed to parse key: %v\n", err)
}
m := testMsgEx()
@@ -73,11 +73,11 @@ func TestSigningDifferentZone(t *testing.T) {
d := New([]string{"example.org."}, []*DNSKEY{key}, nil, c)
m = d.Sign(state, "example.org.", time.Now().UTC())
if !section(m.Answer, 1) {
- t.Errorf("answer section should have 1 sig")
+ t.Errorf("Answer section should have 1 RRSIG")
t.Logf("%+v\n", m)
}
if !section(m.Ns, 1) {
- t.Errorf("authority section should have 1 sig")
+ t.Errorf("Authority section should have 1 RRSIG")
t.Logf("%+v\n", m)
}
}
@@ -91,7 +91,7 @@ func TestSigningCname(t *testing.T) {
state := request.Request{Req: m}
m = d.Sign(state, "miek.nl.", time.Now().UTC())
if !section(m.Answer, 1) {
- t.Errorf("answer section should have 1 sig")
+ t.Errorf("Answer section should have 1 RRSIG")
}
}
@@ -103,12 +103,24 @@ func TestZoneSigningDelegation(t *testing.T) {
m := testDelegationMsg()
state := request.Request{Req: m}
m = d.Sign(state, "miek.nl.", time.Now().UTC())
- if !section(m.Ns, 0) {
- t.Errorf("authority section should have 0 sig")
+ if !section(m.Ns, 1) {
+ t.Errorf("Authority section should have 1 RRSIG")
t.Logf("%v\n", m)
}
+
+ ds := 0
+ for i := range m.Ns {
+ if _, ok := m.Ns[i].(*dns.DS); ok {
+ ds++
+ }
+ }
+ if ds != 1 {
+ t.Errorf("Authority section should have 1 DS")
+ t.Logf("%v\n", m)
+
+ }
if !section(m.Extra, 0) {
- t.Errorf("answer section should have 0 sig")
+ t.Errorf("Answer section should have 0 RRSIGs")
t.Logf("%v\n", m)
}
}
@@ -123,7 +135,7 @@ func TestSigningDname(t *testing.T) {
// We sign *everything* we see, also the synthesized CNAME.
m = d.Sign(state, "miek.nl.", time.Now().UTC())
if !section(m.Answer, 3) {
- t.Errorf("answer section should have 3 sig")
+ t.Errorf("Answer section should have 3 RRSIGs")
}
}
@@ -137,7 +149,7 @@ func TestSigningEmpty(t *testing.T) {
state := request.Request{Req: m}
m = d.Sign(state, "miek.nl.", time.Now().UTC())
if !section(m.Ns, 2) {
- t.Errorf("authority section should have 2 sig")
+ t.Errorf("Authority section should have 2 RRSIGs")
}
}
diff --git a/plugin/dnssec/responsewriter.go b/plugin/dnssec/responsewriter.go
index 793cbcdd0..5a38abac7 100644
--- a/plugin/dnssec/responsewriter.go
+++ b/plugin/dnssec/responsewriter.go
@@ -22,8 +22,7 @@ func (d *ResponseWriter) WriteMsg(res *dns.Msg) error {
// which zone it should be.
state := request.Request{W: d.ResponseWriter, Req: res}
- qname := state.Name()
- zone := plugin.Zones(d.d.zones).Matches(qname)
+ zone := plugin.Zones(d.d.zones).Matches(state.Name())
if zone == "" {
return d.ResponseWriter.WriteMsg(res)
}
diff --git a/plugin/dnssec/rrsig.go b/plugin/dnssec/rrsig.go
index c68413622..d67cdc926 100644
--- a/plugin/dnssec/rrsig.go
+++ b/plugin/dnssec/rrsig.go
@@ -8,7 +8,7 @@ func (k *DNSKEY) newRRSIG(signerName string, ttl, incep, expir uint32) *dns.RRSI
sig.Hdr.Rrtype = dns.TypeRRSIG
sig.Algorithm = k.K.Algorithm
- sig.KeyTag = k.keytag
+ sig.KeyTag = k.tag
sig.SignerName = signerName
sig.Hdr.Ttl = ttl
sig.OrigTtl = origTTL
diff --git a/plugin/dnssec/setup.go b/plugin/dnssec/setup.go
index 2f5c21d97..012ba5b3d 100644
--- a/plugin/dnssec/setup.go
+++ b/plugin/dnssec/setup.go
@@ -77,7 +77,7 @@ func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, int, error) {
zones[i] = plugin.Host(zones[i]).Normalize()
}
- // Check if each keys owner name can actually sign the zones we want them to sign
+ // Check if each keys owner name can actually sign the zones we want them to sign.
for _, k := range keys {
kname := plugin.Name(k.K.Header().Name)
ok := false
@@ -88,7 +88,7 @@ func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, int, error) {
}
}
if !ok {
- return zones, keys, capacity, fmt.Errorf("key %s (keyid: %d) can not sign any of the zones", string(kname), k.keytag)
+ return zones, keys, capacity, fmt.Errorf("key %s (keyid: %d) can not sign any of the zones", string(kname), k.tag)
}
}