Merge branch 'master' of github.com:miekg/dns

This commit is contained in:
Miek Gieben 2012-07-04 09:54:52 +02:00
commit c37493cbbf
2 changed files with 36 additions and 199 deletions

View File

@ -1,5 +1,12 @@
package dns
import (
"net"
"strconv"
)
const hexDigit = "0123456789abcdef"
// Everything is assumed in the ClassINET class. If
// you need other classes you are on your own.
@ -311,3 +318,32 @@ func Fqdn(s string) string {
}
return s + "."
}
// Copied from the official Go code
// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address addr suitable for rDNS (PTR) record lookup or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
ip := net.ParseIP(addr)
if ip == nil {
return "", &Error{Err: "unrecognized address", Name: addr}
}
if ip.To4() != nil {
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
}
// Must be IPv6
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
// Add it, in reverse, to the buffer
for i := len(ip) - 1; i >= 0; i-- {
v := ip[i]
buf = append(buf, hexDigit[v&0xF])
buf = append(buf, '.')
buf = append(buf, hexDigit[v>>4])
buf = append(buf, '.')
}
// Append "ip6.arpa." and return (buf already has the final .)
buf = append(buf, "ip6.arpa."...)
return string(buf), nil
}

199
lookup.go
View File

@ -1,199 +0,0 @@
package dns
// This file is in flux
import (
"math/rand"
"strings"
"time"
)
type SecurityStatus int
const (
SECURE SecurityStatus = iota
INSECURE
BOGUS
INDETERMINATE
)
// Check if the returned message has a delegation signer record
// Algo:
// The auth section's owner name (should be all equal) - seperate check!
// The ownername of the DS records must match the right side of the qname
//
func AssertDelegationSigner(m *Msg, trustdb []*RR_DNSKEY) error {
// look for the DS(s)
dss := make([]*RR_DS, 0)
// If there are ddssen, there should also be a SIG (what if not?)
var sig *RR_RRSIG
for _, r := range m.Ns {
if d, ok := r.(*RR_DS); ok {
dss = append(dss, d)
continue
}
if s, ok := r.(*RR_RRSIG); ok {
if s.TypeCovered == TypeDS {
sig = s
}
}
}
if len(dss) == 0 {
// No DSs found ...
return nil
}
println("DSs found", len(dss))
if sig == nil {
// No SIG found ...
return nil
}
println("SIG found")
// Ownername of the DSs should match the qname
if CompareLabels(dss[0].Header().Name, m.Question[0].Name) == 0 {
// No match
}
// Optionally keep track of these comparison, it should increase
println("Match found between delegation DS and qname")
println(dss[0].String())
println(sig.String())
return nil
}
// Types of answers (without looking the RFCs)
// len(m.Ns) > 0
// NS records in there? -> delegation (rcode should be rcode.Success)
// - secure delegation -> DS should be there
// - insecure delegation -> Proof of no DS (either NSEC or NSEC3)
// - plain old DNS delegation -> ...
// SOA record in there? -> nxdomain (rcode should be rcode.Nxdomain)
// Lookup does a (secure) DNS lookup. The message m contains
// the question to be asked. Lookup returns last packet seen
// which is either the answer or a packet somewhere in the
// tree where the error occured.
// TODO: check return code - see unbound for what we want
//
func Lookup(m *Msg) (*Msg, error) {
// This is actually what needs to be done when parsing packets too
a, aaaa := primingZone()
ds := primingTrust()
for i, r := range a {
println(i, r)
}
for i, r := range aaaa {
println(i, r)
}
for i, r := range ds {
println(i, r.String())
}
c := new(Client)
a1 := randomAddress(a)
println(a1)
n, _, _, e := c.ExchangeRtt(m, a1+":53")
if e == nil {
println(n.String())
} else {
println(e.Error())
return nil, e
}
// n is our reply, deal with it
// Check for DS
// Check for DS absent (NSEC/NSEC3)
if len(n.Ns) > 0 && len(n.Answer) == 0 && n.Rcode == RcodeSuccess { // Referral
// the ns name of the nameservers should match the right most labels. Check the answer
println("Referral")
for i, j := range addrFromReferral4(n) {
println(i, j)
}
}
return nil, nil
}
// Parse a referral packet and return two lists (v4 and v6) of
// ip addresses to try next. As the NS records in a referral
// are not signed (the belong to the child), no validation takes
// place at this step.
func parseReferral(m *Msg) ([]*RR_A, []*RR_AAAA) {
return nil, nil
}
// Parse the builtin root zone and return two lists (v4 and v6) of
// ip addresses to try.
// Glue checking this is -- should be done much nicer/better
func primingZone() (a, aaaa []string) {
nss := make(map[string]bool) // List of ns names
// Walk the records, get each NS for . and look for the addresses
for rr := range ParseZone(strings.NewReader(NamedRoot), "", "named.root") {
if rr.RR.Header().Name == "." && rr.RR.Header().Rrtype == TypeNS {
nss[rr.RR.(*RR_NS).Ns] = true
continue
}
if rr.RR.Header().Rrtype == TypeA {
for n, _ := range nss {
if rr.RR.Header().Name == n {
a = append(a, rr.RR.(*RR_A).A.String())
}
}
continue
}
if rr.RR.Header().Rrtype == TypeAAAA {
for n, _ := range nss {
if rr.RR.Header().Name == n {
aaaa = append(aaaa, rr.RR.(*RR_AAAA).AAAA.String())
}
}
}
}
// Randomize
return
}
// Validate the root key with the DS records we've gotten offline
func createTrustDB(dss []*RR_DS, a, aaaa []string) *[]RR_DNSKEY {
// Query a root server, get the DNSKEY, toDS() and check
return nil
}
// Parse the builtin trust anchor and return the DS records
func primingTrust() []*RR_DS {
ta, _ := ReadTrustAnchor(strings.NewReader(RootAnchorXML))
// Don't care about validity just yet
dss := make([]*RR_DS, 0)
for _, t := range ta {
dss = append(dss, t.Anchor)
}
return dss
}
func randomAddress(list []string) string {
rand.Seed(int64(time.Now().Nanosecond()))
if len(list) == 0 {
return ""
}
return list[rand.Intn(len(list))]
}
// Pull the addresses out of the referral message
// Check the zone
func addrFromReferral4(m *Msg) (addr []string) {
for _, ns := range m.Ns {
if ns.Header().Rrtype != TypeNS {
continue
}
for _, a := range m.Extra {
if a.Header().Rrtype != TypeA {
continue
}
if ns.(*RR_NS).Ns == a.Header().Name {
addr = append(addr, a.(*RR_A).A.String())
}
}
}
return
}