NSEC3 encoding works

Only for 1 windows, but dig has stopped complaining. This
needs to be streamlined a little, but its looking good.
This commit is contained in:
Miek Gieben 2012-01-14 11:08:42 +01:00
parent 32a0b4a6f2
commit 03a8ee13a2
4 changed files with 94 additions and 46 deletions

View File

@ -9,12 +9,13 @@ implemented in the library.
Features:
* UDP/TCP queries, IPv4 and IPv6;
* TSIG;
* EDNS0;
* AXFR/IXFR;
* DNS name compression;
* Client and server side programming (mimicking the http package);
* Asynchronous queries for client and server;
* DNSSEC;
* EDNS0;
* AXFR/IXFR;
* TSIG;
* DNS name compression;
* RFC 1035 zone file parsing.
Sample programs can be found in the `_examples` directory. They can
@ -50,7 +51,7 @@ Miek Gieben - 2010-2012 - miek@miek.nl
* 4635 - HMAC SHA TSIG
* 4892 - id.server
* 5001 - NSID
* 5155 - NSEC
* 5155 - NSEC3
* 5933 - GOST
* 5936 - AXFR
* xxxx - ECDSA

View File

@ -75,12 +75,28 @@ func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
m.Extra = append(m.Extra, t)
}
nsec3 := new(dns.RR_NSEC3)
nsec3.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeNSEC3, Class: dns.ClassINET, Ttl: 0}
nsec3.Hash = dns.SHA1
nsec3.Flags = 0
nsec3.Iterations = 1
nsec3.Salt = "AABB"
nsec3.SaltLength = uint8(len(nsec3.Salt)/2)
nsec3.NextDomain = "miek.nl."
// nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeMX, dns.TypeTXT, 4000, 4001}
// nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeMX, dns.TypeTXT}
nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeSOA}
nsec3.HashNames("miek.nl.")
m.Extra = append(m.Extra, nsec3)
b, ok := m.Pack()
fmt.Printf("%v\n", m.String())
if !ok {
log.Print("Packing failed")
//write formerr back?
return
m.SetRcode(r, dns.RcodeServerFailure)
m.Extra = nil
m.Answer = nil
b, _ = m.Pack()
}
w.Write(b)
}

54
msg.go
View File

@ -16,6 +16,7 @@ import (
"encoding/base32"
"encoding/base64"
"encoding/hex"
"fmt"
"math/rand"
"net"
"reflect"
@ -408,11 +409,34 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
off++
}
case "NSEC": // NSEC/NSEC3
// This is the uint16 type bitmap
// TODO(mg): overflow
lastwindow := uint16(0)
octet := uint16(0)
for j := 0; j < val.Field(i).Len(); j++ {
var _ = byte(fv.Index(j).Uint())
t := uint16((fv.Index(j).Uint()))
window := uint16(t / 256)
if lastwindow != window {
// New window
off += 2 + int(octet)
}
octet := (t - window*256) / 8
bit := t - (window * 256) - (octet * 8)
println("Setting window", off, "to", byte(window))
msg[off] = byte(window)
println("Setting octet", off+1, "to", byte(octet+1))
msg[off+1] = byte(octet+1)
println("Setting value", off+1+1+int(octet), "to", byte(1<<bit))
msg[off+1+1+int(octet)] |= byte(1 << bit)
println(t, window, octet, bit, 1<<bit)
fmt.Printf("%b\n", msg[off+2+int(octet)])
lastwindow = window
}
// handle type bit maps
// TODO(mg)
// off++
println("off", off)
}
case reflect.Struct:
off, ok = packStructValue(fv, msg, off, compression, compress)
@ -464,14 +488,6 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
switch val.Type().Field(i).Tag {
default:
return lenmsg, false
case "base32":
b32, err := packBase32([]byte(s))
if err != nil {
println("dns: overflow packing base32")
return lenmsg, false
}
copy(msg[off:off+len(b32)], b32)
off += len(b32)
case "base64":
b64, err := packBase64([]byte(s))
if err != nil {
@ -492,6 +508,20 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
println("dns: overflow packing domain-name", off)
return lenmsg, false
}
case "size-base32":
// This is purely for NSEC3 atm, the previous byte must
// holds the length of the encoded string. As NSEC3
// is only defined to SHA1, the hashlength is 20 (160 bits)
msg[off-1] = 20 // Set HashLength... TODO(mg): check
fallthrough
case "base32":
b32, err := packBase32([]byte(s))
if err != nil {
println("dns: overflow packing base32")
return lenmsg, false
}
copy(msg[off:off+len(b32)], b32)
off += len(b32)
case "size-hex":
fallthrough
case "hex":
@ -594,7 +624,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
fv.Set(reflect.ValueOf(opt))
off = off1 + int(optlen)
case "NSEC": // NSEC/NSEC3
// Rest of the Record it the type bitmap
// Rest of the Record is the type bitmap
rdlength := int(val.FieldByName("Hdr").FieldByName("Rdlength").Uint())
rdlength -= (1 + 1 + 2 + len(val.FieldByName("NextDomain").String()) + 1)
if off+1 > lenmsg {

View File

@ -11,13 +11,13 @@
//
// 3.2.4 - Table Of Metavalues Used In Prerequisite Section
//
// CLASS TYPE RDATA Meaning Function
// ----------------------------------------------------------------------------
// ANY ANY empty Name is in use NameUsed
// ANY rrset empty RRset exists (value independent) RRsetUsedNoRdata
// NONE ANY empty Name is not in use NameNotUsed
// NONE rrset empty RRset does not exist RRsetNotUsed
// zone rrset rr RRset exists (value dependent) RRsetUsedRdata
// CLASS TYPE RDATA Meaning Function
// --------------------------------------------------------------
// ANY ANY empty Name is in use NameUsed
// ANY rrset empty RRset exists (value indep) RRsetUsedNoRdata
// NONE ANY empty Name is not in use NameNotUsed
// NONE rrset empty RRset does not exist RRsetNotUsed
// zone rrset rr RRset exists (value dep) RRsetUsedRdata
//
// The prerequisite section can also be left empty.
// If you have decided an the prerequisites you can tell what RRs should
@ -25,16 +25,17 @@
// what function to call.
// 3.4.2.6 - Table Of Metavalues Used In Update Section
//
// CLASS TYPE RDATA Meaning Function
// -------------------------------------------------------------------------
// ANY ANY empty Delete all RRsets from a name NameDelete
// ANY rrset empty Delete an RRset RRsetDelete
// NONE rrset rr Delete an RR from an RRset RRsetDeleteRR
// zone rrset rr Add to an RRset RRsetAddRdata
// CLASS TYPE RDATA Meaning Function
// ---------------------------------------------------------------
// ANY ANY empty Delete all RRsets from name NameDelete
// ANY rrset empty Delete an RRset RRsetDelete
// NONE rrset rr Delete an RR from RRset RRsetDeleteRR
// zone rrset rr Add to an RRset RRsetAddRdata
//
package dns
// NewUpdate creates a new DNS update packet, which is a normal DNS message.
// NewUpdate creates a new DNS update packet. This returns a normal
// dns *Msg, but sets some options.
func NewUpdate(zone string, class uint16) *Msg {
u := new(Msg)
u.MsgHdr.Response = false
@ -49,13 +50,13 @@ func NewUpdate(zone string, class uint16) *Msg {
//
// 3.2.4 - Table Of Metavalues Used In Prerequisite Section
//
// CLASS TYPE RDATA Meaning Function
// ----------------------------------------------------------------------
// ANY ANY empty Name is in use NameUsed
// ANY rrset empty RRset exists (value independent) RRsetUsedNoRdata
// NONE ANY empty Name is not in use NameNotUsed
// NONE rrset empty RRset does not exist RRsetNotUsed
// zone rrset rr RRset exists (value dependent) RRsetUsedRdata
// CLASS TYPE RDATA Meaning Function
// ---------------------------------------------------------------
// ANY ANY empty Name is in use NameUsed
// ANY rrset empty RRset exists (value indep) RRsetUsedNoRdata
// NONE ANY empty Name is not in use NameNotUsed
// NONE rrset empty RRset does not exist RRsetNotUsed
// zone rrset rr RRset exists (value dep) RRsetUsedRdata
// NameUsed sets the RRs in the prereq section to
// "Name is in use" RRs. RFC 2136 section 2.4.4.
@ -116,12 +117,12 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
//
// 3.4.2.6 - Table Of Metavalues Used In Update Section
//
// CLASS TYPE RDATA Meaning Function
// --------------------------------------------------------------------------
// ANY ANY empty Delete all RRsets from a name NameDelete
// ANY rrset empty Delete an RRset RRsetDelete
// NONE rrset rr Delete an RR from an RRset RRsetDeleteRR
// zone rrset rr Add to an RRset RRsetAddRdata
// CLASS TYPE RDATA Meaning Function
// -----------------------------------------------------------------
// ANY ANY empty Delete all RRsets from name NameDelete
// ANY rrset empty Delete an RRset RRsetDelete
// NONE rrset rr Delete an RR from RRset RRsetDeleteRR
// zone rrset rr Add to an RRset RRsetAddRdata
// RRsetAddRdata adds an complete RRset, see RFC 2136 section 2.5.1
func (u *Msg) RRsetAddRdata(rr []RR) {