dns/nsecx.go

126 lines
3.2 KiB
Go
Raw Normal View History

2013-05-13 00:15:52 +10:00
// Copyright 2011 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
2011-01-28 01:52:58 +11:00
package dns
2011-03-08 07:56:36 +11:00
import (
2011-12-10 07:45:57 +11:00
"crypto/sha1"
2011-03-08 08:47:20 +11:00
"hash"
"io"
2011-03-08 08:47:20 +11:00
"strings"
2011-03-08 07:56:36 +11:00
)
2012-01-22 21:33:51 +11:00
const (
_ = iota
2012-08-20 17:39:10 +10:00
_NSEC3_NXDOMAIN
_NSEC3_NODATA
2012-01-22 21:33:51 +11:00
)
2011-03-08 08:47:20 +11:00
type saltWireFmt struct {
Salt string `dns:"size-hex"`
2011-03-08 08:47:20 +11:00
}
2011-01-28 01:52:58 +11:00
2012-12-02 20:14:53 +11:00
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string.
2012-01-22 20:52:06 +11:00
func HashName(label string, ha uint8, iter uint16, salt string) string {
2011-03-08 08:47:20 +11:00
saltwire := new(saltWireFmt)
saltwire.Salt = salt
wire := make([]byte, DefaultMsgSize)
n, err := PackStruct(saltwire, wire, 0)
if err != nil {
2011-03-08 08:47:20 +11:00
return ""
}
wire = wire[:n]
2011-03-10 00:27:41 +11:00
name := make([]byte, 255)
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
if err != nil {
2011-03-08 08:47:20 +11:00
return ""
}
2011-03-10 00:27:41 +11:00
name = name[:off]
2011-03-08 08:47:20 +11:00
var s hash.Hash
switch ha {
2011-07-09 01:27:44 +10:00
case SHA1:
2011-03-08 08:47:20 +11:00
s = sha1.New()
2011-03-24 19:24:49 +11:00
default:
return ""
2011-03-08 08:47:20 +11:00
}
// k = 0
2011-03-10 00:27:41 +11:00
name = append(name, wire...)
2011-12-17 05:42:30 +11:00
io.WriteString(s, string(name))
nsec3 := s.Sum(nil)
2011-03-24 19:24:49 +11:00
// k > 0
2012-01-22 20:52:06 +11:00
for k := uint16(0); k < iter; k++ {
2011-03-24 19:24:49 +11:00
s.Reset()
nsec3 = append(nsec3, wire...)
2011-12-17 05:42:30 +11:00
io.WriteString(s, string(nsec3))
2011-12-17 01:12:01 +11:00
nsec3 = s.Sum(nil)
2011-03-24 19:24:49 +11:00
}
2011-03-08 08:47:20 +11:00
return unpackBase32(nsec3)
2011-03-08 07:56:36 +11:00
}
2011-03-10 04:54:55 +11:00
2012-06-06 23:27:35 +10:00
// Implement the HashNames method of Denialer
func (rr *NSEC3) HashNames(domain string) {
2012-09-02 19:45:29 +10:00
rr.Header().Name = strings.ToLower(HashName(rr.Header().Name, rr.Hash, rr.Iterations, rr.Salt)) + "." + domain
rr.NextDomain = HashName(rr.NextDomain, rr.Hash, rr.Iterations, rr.Salt)
2012-01-22 20:52:06 +11:00
}
2012-06-06 23:27:35 +10:00
// Implement the Match method of Denialer
func (rr *NSEC3) Match(domain string) bool {
2012-09-02 19:45:29 +10:00
return strings.ToUpper(SplitLabels(rr.Header().Name)[0]) == strings.ToUpper(HashName(domain, rr.Hash, rr.Iterations, rr.Salt))
2012-01-22 21:33:51 +11:00
}
2012-06-06 23:27:35 +10:00
// Implement the Match method of Denialer
func (rr *NSEC) Match(domain string) bool {
2012-09-02 19:45:29 +10:00
return strings.ToUpper(rr.Header().Name) == strings.ToUpper(domain)
2012-06-06 23:27:35 +10:00
}
func (rr *NSEC3) MatchType(rrtype uint16) bool {
2012-09-02 19:45:29 +10:00
for _, t := range rr.TypeBitMap {
2012-06-06 23:27:35 +10:00
if t == rrtype {
return true
}
if t > rrtype {
return false
}
}
return false
}
func (rr *NSEC) MatchType(rrtype uint16) bool {
2012-09-02 19:45:29 +10:00
for _, t := range rr.TypeBitMap {
2012-06-06 23:27:35 +10:00
if t == rrtype {
return true
}
if t > rrtype {
return false
}
}
return false
}
2012-06-06 15:36:45 +10:00
// Cover checks if domain is covered by the NSEC3 record. Domain must be given in plain text (i.e. not hashed)
// TODO(mg): this doesn't loop around
// TODO(mg): make a CoverHashed variant?
func (rr *NSEC3) Cover(domain string) bool {
2012-09-02 19:45:29 +10:00
hashdom := strings.ToUpper(HashName(domain, rr.Hash, rr.Iterations, rr.Salt))
nextdom := strings.ToUpper(rr.NextDomain)
2012-09-11 04:51:19 +10:00
owner := strings.ToUpper(SplitLabels(rr.Header().Name)[0]) // The hashed part
2012-09-02 19:45:29 +10:00
apex := strings.ToUpper(HashName(strings.Join(SplitLabels(rr.Header().Name)[1:], "."), rr.Hash, rr.Iterations, rr.Salt)) + "." // The name of the zone
// if nextdomain equals the apex, it is considered The End. So in that case hashdom is always less then nextdomain
if hashdom > owner && nextdom == apex {
return true
}
if hashdom > owner && hashdom <= nextdom {
return true
}
return false
2011-03-10 04:54:55 +11:00
}
2011-09-16 04:13:21 +10:00
2012-03-09 07:16:51 +11:00
// Cover checks if domain is covered by the NSEC record. Domain must be given in plain text.
func (rr *NSEC) Cover(domain string) bool {
2012-03-09 07:16:51 +11:00
return false
}