From a60238bddec4c2af136ba9b9a7d1c24c07217345 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Fri, 14 Jan 2011 11:57:28 +0100 Subject: [PATCH] Remove unwanted wire conversion functions --- dns.go | 107 +++++-------------------------- dnssec.go | 141 ++++++++++++++++++++++++++++++++--------- resolver/resolver.go | 2 +- responder/responder.go | 16 ++++- tsig.go | 4 +- 5 files changed, 146 insertions(+), 124 deletions(-) diff --git a/dns.go b/dns.go index e81a1b14..108140b2 100644 --- a/dns.go +++ b/dns.go @@ -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 "" - } - return e.Error + if e == nil { + return "" + } + 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 } diff --git a/dnssec.go b/dnssec.go index 9744ed77..cb6401b2 100644 --- a/dnssec.go +++ b/dnssec.go @@ -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 diff --git a/resolver/resolver.go b/resolver/resolver.go index be0c0bfd..dc3b7d58 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -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. diff --git a/responder/responder.go b/responder/responder.go index cc344637..d241dbf9 100644 --- a/responder/responder.go +++ b/responder/responder.go @@ -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 diff --git a/tsig.go b/tsig.go index 2dcc0398..04489a6b 100644 --- a/tsig.go +++ b/tsig.go @@ -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