// Sign signs the message m. 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, // starting 3 hours ago. func (d Dnssec) Sign(state middleware.State, zone string, now time.Time) *dns.Msg { req := state.Req mt, _ := middleware.Classify(req) // TODO(miek): need opt record here? if mt == middleware.Delegation { return req } incep, expir := incepExpir(now) if mt == middleware.NameError { if req.Ns[0].Header().Rrtype != dns.TypeSOA || len(req.Ns) > 1 { return req } ttl := req.Ns[0].Header().Ttl if sigs, err := d.sign(req.Ns, zone, ttl, incep, expir); err == nil { req.Ns = append(req.Ns, sigs...) } if sigs, err := d.nsec(state.Name(), zone, ttl, incep, expir); err == nil { req.Ns = append(req.Ns, sigs...) } if len(req.Ns) > 1 { // actually added nsec and sigs, reset the rcode req.Rcode = dns.RcodeSuccess } return req } for _, r := range rrSets(req.Answer) { ttl := r[0].Header().Ttl if sigs, err := d.sign(r, zone, ttl, incep, expir); err == nil { req.Answer = append(req.Answer, sigs...) } } for _, r := range rrSets(req.Ns) { ttl := r[0].Header().Ttl if sigs, err := d.sign(r, zone, ttl, incep, expir); err == nil { req.Ns = append(req.Ns, sigs...) } } for _, r := range rrSets(req.Extra) { ttl := r[0].Header().Ttl if sigs, err := d.sign(r, zone, ttl, incep, expir); err == nil { req.Extra = append(sigs, req.Extra...) // prepend to leave OPT alone } } return req }
func (c *CachingResponseWriter) WriteMsg(res *dns.Msg) error { do := false mt, opt := middleware.Classify(res) if opt != nil { do = opt.Do() } key := cacheKey(res, mt, do) c.set(res, key, mt) if c.cap != 0 { setCap(res, uint32(c.cap.Seconds())) } return c.ResponseWriter.WriteMsg(res) }
func TestCache(t *testing.T) { c, crr := newTestCache() for _, tc := range cacheTestCases { m := tc.in.Msg() m = cacheMsg(m, tc) do := tc.in.Do mt, _ := middleware.Classify(m) key := cacheKey(m, mt, do) crr.set(m, key, mt) name := middleware.Name(m.Question[0].Name).Normalize() qtype := m.Question[0].Qtype i, ok := c.get(name, qtype, do) if !ok && !m.Truncated { t.Errorf("Truncated message should not have been cached") } if ok { resp := i.toMsg(m) if !test.Header(t, tc.Case, resp) { t.Logf("%v\n", resp) continue } if !test.Section(t, tc.Case, test.Answer, resp.Answer) { t.Logf("%v\n", resp) } if !test.Section(t, tc.Case, test.Ns, resp.Ns) { t.Logf("%v\n", resp) } if !test.Section(t, tc.Case, test.Extra, resp.Extra) { t.Logf("%v\n", resp) } } } }