fix merge

This commit is contained in:
Miek Gieben 2012-09-07 20:37:45 +02:00
commit cacd7c4dcd
6 changed files with 83 additions and 25 deletions

View File

@ -1,8 +1,9 @@
# TODO
* 'q' standardize ipv6 input with [::1]#53 ?
* put axfr in q
* make example from chaos
* Support for on-the-fly-signing
* (Re)sign zonefiles
## Nice to have

View File

@ -3,6 +3,7 @@ package dns
import (
"net"
"strconv"
"strings"
)
const hexDigit = "0123456789abcdef"
@ -220,7 +221,7 @@ func IsDomainName(s string) (uint8, uint8, bool) { // copied from net package.
// IsSubDomain checks if child is indeed a child of the parent.
func IsSubDomain(parent, child string) bool {
// Entire child is contained in parent
return CompareLabels(parent, child) == LenLabels(parent)
return CompareLabels(strings.ToLower(parent), strings.ToLower(child)) == LenLabels(parent)
}
// IsFqdn checks if a domain name is fully qualified.

View File

@ -16,7 +16,9 @@ func (k *RR_DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
return k.ReadPrivateKey(strings.NewReader(s), "")
}
// NewPrivateKey reads a private key from the io.Reader q. The public key must be
// NewPrivateKey reads a private key from the io.Reader q. The string file is
// only used in error reporting.
// The public key must be
// known, because some cryptographics algorithms embed the public inside the privatekey.
func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
m, e := parseKey(q, file)

View File

@ -34,7 +34,8 @@ func SplitLabels(s string) []string {
// CompareLabels compares the strings s1 and s2 and
// returns how many labels they have in common starting from the right.
// The comparison stops at the first inequality.
// The comparison stops at the first inequality. The labels are not downcased
// before the comparison.
//
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
// www.miek.nl. and www.bla.nl. have one label in common: nl

View File

@ -171,7 +171,7 @@ func ListenAndServe(addr string, network string, handler Handler) error {
func (mux *ServeMux) match(zone string, t uint16) Handler {
zone = toRadixName(zone)
if h := mux.m.Find(zone); h != nil && h.Value != nil {
if h, e := mux.m.Find(zone); e {
// If we got queried for a DS record, we must see if we
// if we also serve the parent. We then redirect it.
if t == TypeDS {
@ -180,12 +180,10 @@ func (mux *ServeMux) match(zone string, t uint16) Handler {
}
}
return h.Value.(Handler)
}
// Best matching one.
if h := mux.m.Predecessor(zone); h != nil && h.Value != nil {
} else {
return h.Value.(Handler)
}
return nil
panic("dns: not reached")
}
// Handle adds a handler to the ServeMux for pattern.

87
zone.go
View File

@ -6,6 +6,7 @@ import (
"github.com/miekg/radix"
"strings"
"sync"
"time"
)
// Zone represents a DNS zone. It's safe for concurrent use by
@ -15,8 +16,37 @@ type Zone struct {
Wildcard int // Whenever we see a wildcard name, this is incremented
*radix.Radix // Zone data
mutex *sync.RWMutex
// timemodified?
expired bool // Slave zone is expired
}
// SignatureConfig holds the parameters for zone (re)signing. This
// is copied from OpenDNSSEC. See:
// https://wiki.opendnssec.org/display/DOCS/kasp.xml
type SignatureConfig struct {
// Validity period of the signatures, typically 2 to 4 weeks.
Validity time.Duration
// When the end of the validity approaches, how much time should remain
// before we start to resign. Typical value is 3 days.
Refresh time.Duration
// Jitter is an amount of time added or subtracted from the
// expiration time to ensure not all signatures expire a the same time.
// Typical value is 12 hours.
Jitter time.Duration
// InceptionOffset is subtracted from the inception time to ensure badly
// calibrated clocks on the internet can still validate a signature.
// Typical value is 300 seconds.
InceptionOffset time.Duration
}
func newSignatureConfig() *SignatureConfig {
return &SignatureConfig{time.Duration(4*7*24) * time.Hour, time.Duration(3*24) * time.Hour, time.Duration(12) * time.Hour, time.Duration(300) * time.Second}
}
// DefaultSignaturePolicy has the following values. Validity is 4 weeks,
// Refresh is set to 3 days, Jitter to 12 hours and InceptionOffset to 300 seconds.
var DefaultSignatureConfig = newSignatureConfig()
// NewZone creates an initialized zone with Origin set to origin.
func NewZone(origin string) *Zone {
if origin == "" {
@ -60,11 +90,18 @@ func toRadixName(d string) string {
}
s := ""
for _, l := range SplitLabels(d) {
if s == "" {
s = strings.ToLower(l) + s
continue
}
s = strings.ToLower(l) + "." + s
}
return "." + s
return s
}
func (z *Zone) String() string {
return z.Radix.String()
}
// Insert inserts an RR into the zone. There is no check for duplicate data, although
// Remove will remove all duplicates.
@ -73,12 +110,14 @@ func (z *Zone) Insert(r RR) error {
return &Error{Err: "out of zone data", Name: r.Header().Name}
}
// TODO(mg): quick check for doubles?
key := toRadixName(r.Header().Name)
z.mutex.Lock()
zd := z.Radix.Find(key)
if zd == nil {
zd, exact := z.Radix.Find(key)
if !exact {
// Not an exact match, so insert new value
defer z.mutex.Unlock()
// Check if its a wildcard name
// Check if it's a wildcard name
if len(r.Header().Name) > 1 && r.Header().Name[0] == '*' && r.Header().Name[1] == '.' {
z.Wildcard++
}
@ -123,8 +162,8 @@ func (z *Zone) Insert(r RR) error {
func (z *Zone) Remove(r RR) error {
key := toRadixName(r.Header().Name)
z.mutex.Lock()
zd := z.Radix.Find(key)
if zd == nil {
zd, exact := z.Radix.Find(key)
if !exact {
defer z.mutex.Unlock()
return nil
}
@ -161,23 +200,39 @@ func (z *Zone) Remove(r RR) error {
// Find looks up the ownername s in the zone and returns the
// data when found or nil when nothing is found.
// We can do better here, and include NXDOMAIN also. Much more efficient, only
// 1 tree walk.
func (z *Zone) Find(s string) *ZoneData {
z.mutex.RLock()
defer z.mutex.RUnlock()
zd := z.Radix.Find(toRadixName(s))
if zd == nil {
zd, e := z.Radix.Find(toRadixName(s))
if !e {
return nil
}
return zd.Value.(*ZoneData)
}
// Predecessor searches the zone for a name shorter than s.
func (z *Zone) Predecessor(s string) *ZoneData {
z.mutex.RLock()
defer z.mutex.RUnlock()
zd := z.Radix.Predecessor(toRadixName(s))
if zd == nil {
return nil
// Sign (re)signes the zone z. It adds keys to the zone (if not already there)
// and signs the keys with the KSKs and the rest of the zone with the ZSKs.
// NSEC is used for authenticated denial
// of existence. If config is nil DefaultSignatureConfig is used.
// TODO(mg): allow interaction with hsm
func (z *Zone) Sign(keys []*RR_DNSKEY, privkeys []PrivateKey, config *SignatureConfig) error {
if config == nil {
config = DefaultSignatureConfig
}
return zd.Value.(*ZoneData)
// TODO(mg): concurrently walk the zone and sign the rrsets
// TODO(mg): nsec, or next pointer. Need to be a single tree-op
return nil
}
// Sign each ZoneData in place.
// TODO(mg): assume not signed
func signZoneData(zd *ZoneData, privkeys []PrivateKey, signername string, config *SignatureConfig) {
if zd.NonAuth == true {
return
}
//s := new(RR_RRSIG)
// signername
}