Remove unwanted wire conversion functions

This commit is contained in:
Miek Gieben 2011-01-14 11:57:28 +01:00
parent 728b575b60
commit a60238bdde
5 changed files with 146 additions and 124 deletions

107
dns.go
View File

@ -10,7 +10,9 @@
// * 1876 - LOC record (incomplete)
// * 1995 - IXFR
// * 1996 - DNS notify
// * 2181 - RRset definition
// * 2537 - RSAMD5 DNS keys
// * 2065 - DNSSEC (updated in later RFCs)
// * 2671 - EDNS
// * 2845 - TSIG
// * 2915 - NAPTR record (incomplete)
@ -27,24 +29,22 @@ package dns
import (
"strconv"
"os"
"net"
)
const Year68 = 2 << (32 - 1)
type Error struct {
Error string
Name string
Server string
Timeout bool
Error string
Name string
Server string
Timeout bool
}
func (e *Error) String() string {
if e == nil {
return "<nil>"
}
return e.Error
if e == nil {
return "<nil>"
}
return e.Error
}
type RR interface {
@ -93,85 +93,12 @@ func (h *RR_Header) String() string {
return s
}
func SendTCP(c net.Conn, m []byte) os.Error {
l := make([]byte, 2)
l[0] = byte(len(m) >> 8)
l[1] = byte(len(m))
// First we send the length
_, err := c.Write(l)
if err != nil {
return err
}
// And the the message
_, err = c.Write(m)
if err != nil {
return err
}
return nil
}
func RecvTCP(c net.Conn) ([]byte, os.Error) {
l := make([]byte, 2) // receiver length
// The server replies with two bytes length
_, err := c.Read(l)
if err != nil {
return nil,err
}
length := uint16(l[0])<<8 | uint16(l[1])
if length == 0 {
return nil, &Error{Error: "received nil msg length", Server: c.RemoteAddr().String()}
}
m := make([]byte, length)
n, cerr := c.Read(m)
if cerr != nil {
return nil, cerr
}
i := n
if i < int(length) {
n, err = c.Read(m[i:])
if err != nil {
return nil, err
}
i += n
}
return m, nil
}
// Or expose the pack/unpack functions??
// These were created for dnssec.go, but now that
// that package is included again in dns, they are
// not really needed. These will be removed asap.
// Return the wiredata of rdata portion of a RR.
func WireRdata(r RR) ([]byte, bool) {
buf := make([]byte, 4096) // Too large, need to FIX TODO(mg)
off1, ok := packRR(r, buf, 0)
if !ok {
return nil, false
// Return number of labels in a dname
func labelCount(a string) (c int) {
for _, v := range a {
if v == '.' {
c++
}
}
start := off1 - int(r.Header().Rdlength)
end := start + int(r.Header().Rdlength)
buf = buf[start:end]
return buf, true
}
// Return the wiredata of a domainname (sans compressions).
func WireDomainName(s string) ([]byte, bool) {
buf := make([]byte, 255)
off, ok := packDomainName(s, buf, 0)
if !ok {
return nil, ok
}
buf = buf[:off]
return buf, ok
}
// Return the wiredata of a complete Resource Record.
func WireRR(r RR) ([]byte, bool) {
buf := make([]byte, 4096)
off, ok := packRR(r, buf, 0)
if !ok {
return nil, false
}
buf = buf[:off]
return buf, ok
return
}

141
dnssec.go
View File

@ -37,6 +37,29 @@ const (
HashGOST94
)
// The RRSIG needs to be converted to wireformat with some of
// the rdata (the signature) missing. Use this struct to easy
// the conversion (and re-use the pack/unpack functions.
type rrsigWireFmt struct {
TypeCovered uint16
Algorithm uint8
Labels uint8
OrigTtl uint32
Expiration uint32
Inception uint32
KeyTag uint16
SignerName string "domain-name"
/* No Signature */
}
// Used for converting DNSKEY's rdata to wirefmt.
type dnskeyWireFmt struct {
Flags uint16
Protocol uint8
Algorithm uint8
PubKey string "base64"
}
// Calculate the keytag of the DNSKEY.
func (k *RR_DNSKEY) KeyTag() uint16 {
var keytag int
@ -45,13 +68,17 @@ func (k *RR_DNSKEY) KeyTag() uint16 {
println("Keytag RSAMD5. Todo")
keytag = 0
default:
// Might encode header length too, so that
// we dont need to pack/unpack all the time
// Or a shadow structure, with the wiredata and header
wire, ok := WireRdata(k)
keywire := new(dnskeyWireFmt)
keywire.Flags = k.Flags
keywire.Protocol = k.Protocol
keywire.Algorithm = k.Algorithm
keywire.PubKey = k.PubKey
wire := make([]byte, 2048) // TODO(mg) lenght!
n, ok := packStruct(keywire, wire, 0)
if !ok {
return 0
}
wire = wire[:n]
for i, v := range wire {
if i&1 != 0 {
keytag += int(v) // must be larger than uint32
@ -75,14 +102,24 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
ds.DigestType = uint8(h)
ds.KeyTag = k.KeyTag()
wire, ok := WireRdata(k)
if !ok {
return nil
}
owner, ok1 := WireDomainName(k.Hdr.Name)
keywire := new(dnskeyWireFmt)
keywire.Flags = k.Flags
keywire.Protocol = k.Protocol
keywire.Algorithm = k.Algorithm
keywire.PubKey = k.PubKey
wire := make([]byte, 2048) // TODO(mg) lenght!
n, ok := packStruct(keywire, wire, 0)
if !ok {
return nil
}
wire = wire[:n]
owner := make([]byte, 255)
off, ok1 := packDomainName(k.Hdr.Name, owner, 0)
if !ok1 {
return nil
}
owner = owner[:off]
/*
* from RFC4034
* digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
@ -110,9 +147,32 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
return ds
}
// Sign rrset with k and return the signature RR.
func (k *RR_DNSKEY) Sign(rrset RRset) (*RR_RRSIG) {
return nil
// Sign rrset with k and return the signature RR. There
// is no check if rrset is a proper (RFC 2181) RRSet
func (k *RR_DNSKEY) Sign(rrset RRset, expiration, inception uint32) *RR_RRSIG {
sig := new(RR_RRSIG)
sig.Hdr.Name = rrset[0].Header().Name
sig.Hdr.Class = rrset[0].Header().Class
sig.Hdr.Rrtype = TypeRRSIG
sig.Hdr.Ttl = rrset[0].Header().Ttl // re-use TTL of RRset
sig.Inception = inception
sig.Expiration = expiration
sig.KeyTag = k.KeyTag()
sig.SignerName = k.Hdr.Name
sig.Labels = uint8(labelCount(rrset[0].Header().Name))
sig.TypeCovered = rrset[0].Header().Rrtype
sigwire := new(rrsigWireFmt)
sigwire.TypeCovered = sig.TypeCovered
sigwire.Algorithm = sig.Algorithm
sigwire.Labels = sig.Labels
sigwire.OrigTtl = sig.OrigTtl
sigwire.Expiration = sig.Expiration
sigwire.Inception = sig.Inception
sigwire.KeyTag = sig.KeyTag
sigwire.SignerName = sig.SignerName
return nil
}
// Validate an rrset with the signature and key. This is the
@ -150,11 +210,22 @@ func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
// RFC 4035 5.3.2. Reconstructing the Signed Data
// Copy the sig, except the rrsig data
s1 := &RR_RRSIG{s.Hdr, s.TypeCovered, s.Algorithm, s.Labels, s.OrigTtl, s.Expiration, s.Inception, s.KeyTag, s.SignerName, ""}
signeddata, ok := WireRdata(s1)
sigwire := new(rrsigWireFmt)
sigwire.TypeCovered = s.TypeCovered
sigwire.Algorithm = s.Algorithm
sigwire.Labels = s.Labels
sigwire.OrigTtl = s.OrigTtl
sigwire.Expiration = s.Expiration
sigwire.Inception = s.Inception
sigwire.KeyTag = s.KeyTag
sigwire.SignerName = s.SignerName
// Create the desired binary blob
signeddata := make([]byte, 4096)
n, ok := packStruct(sigwire, signeddata, 0)
if !ok {
return false
}
signeddata = signeddata[:n]
for _, r := range rrset {
h := r.Header()
@ -172,9 +243,16 @@ func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
}
// 6.2. Canonical RR Form. (4) - wildcards, don't understand
// 6.2. Canonical RR Form. (5) - origTTL
ttl := h.Ttl
h.Ttl = s.OrigTtl
wire, ok1 := WireRR(r)
wire := make([]byte, 4096)
off, ok1 := packRR(r, wire, 0)
if !ok1 {
println("Failure to pack")
return false
}
wire = wire[:off]
h.Ttl = ttl // restore the order in the universe
h.Name = name
if !ok1 {
@ -184,22 +262,12 @@ func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
signeddata = append(signeddata, wire...)
}
// Buffer holding the key data
keybuf := make([]byte, 1024)
keybuflen := base64.StdEncoding.DecodedLen(len(k.PubKey))
keybuflen, _ = base64.StdEncoding.Decode(keybuf[0:keybuflen], []byte(k.PubKey))
keybuf = keybuf[:keybuflen]
// Buffer holding the signature
sigbuf := make([]byte, 1024)
sigbuflen := base64.StdEncoding.DecodedLen(len(s.Signature))
sigbuflen, _ = base64.StdEncoding.Decode(sigbuf[0:sigbuflen], []byte(s.Signature))
sigbuf = sigbuf[:sigbuflen]
sigbuf := s.sigBuf() // Get the binary signature data
var err os.Error
switch s.Algorithm {
case AlgRSASHA1, AlgRSASHA256, AlgRSASHA512, AlgRSAMD5:
pubkey := rsaPubKey(keybuf)
pubkey := k.pubKeyRSA() // Get the key
// Setup the hash as defined for this alg.
var h hash.Hash
var ch rsa.PKCS1v15Hash
@ -239,8 +307,23 @@ func (s *RR_RRSIG) PeriodOK() bool {
return ti <= utc && utc <= te
}
// Extra the RSA public key from the buffer
func rsaPubKey(keybuf []byte) *rsa.PublicKey {
// Return the signatures base64 encodedig sigdata as a byte slice.
func (s *RR_RRSIG) sigBuf() []byte {
sigbuf := make([]byte, 1024) // TODO(mg) length!
sigbuflen := base64.StdEncoding.DecodedLen(len(s.Signature))
sigbuflen, _ = base64.StdEncoding.Decode(sigbuf[0:sigbuflen], []byte(s.Signature))
sigbuf = sigbuf[:sigbuflen]
return sigbuf
}
// Extract the RSA public key from the Key record
func (k *RR_DNSKEY) pubKeyRSA() *rsa.PublicKey {
// Buffer holding the key data
keybuf := make([]byte, 1024)
keybuflen := base64.StdEncoding.DecodedLen(len(k.PubKey))
keybuflen, _ = base64.StdEncoding.Decode(keybuf[0:keybuflen], []byte(k.PubKey))
keybuf = keybuf[:keybuflen]
// RFC 2537/3110, section 2. RSA Public KEY Resource Records
// Length is in the 0th byte, unless its zero, then it
// it in bytes 1 and 2 and its a 16 bit number

View File

@ -1,4 +1,4 @@
// Copyright 2009 The Go Authors. All rights reserved.
// 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.

View File

@ -1,10 +1,21 @@
// Copyright 2009 The Go Authors. All rights reserved.
// 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.
// DNS server implementation
// Package responder implements a DNS server
// Package responder implements a DNS server. A nameserver needs to implement
// the Responder interface:
//
// type myserv Server
// func (s *myserv) ResponderUDP(c *net.UDPConn, a net.Addr, in []byte) { /* UDP reply */ }
// func (s *myserv) ResponderTCP(c *net.TCPConn, in []byte) { /* TCP reply */}
// su := new(Server) // create new sever
// su.Address = "127.0.0.1" // listen address
// su.Port = "8053" // listen port
// var us *myserv
// uch :=make(chan bool)
// go su.NewResponder(us, uch) // start the responder
package responder
import (
@ -13,6 +24,7 @@ import (
"dns"
)
// Options for a nameserver.
type Server struct {
Address string // interface to use, for multiple interfaces, use multiple servers
Port string // what port to use

View File

@ -49,7 +49,7 @@ func (rr *RR_TSIG) String() string {
// The following values must be put in wireformat, so that
// the MAC can be calculated
// RFC 2845, section 3.4.2. TSIG Variables
type tsig_generation_fmt struct {
type tsigWireFmt struct {
// From RR_HEADER
Name string "domain-name"
Class uint16
@ -70,7 +70,7 @@ type tsig_generation_fmt struct {
// secret is encoded in base64 in BIND9
func (rr *RR_TSIG) Generate(msg *Msg, secret string) bool {
buf := make([]byte, 4096) // TODO(mg) bufsize!
tsig := new(tsig_generation_fmt)
tsig := new(tsigWireFmt)
// Fill the struct and generate the wiredata
tsig.Name = rr.Header().Name