Allow for escaping of dots in domainnames
This commit is contained in:
parent
865ba16420
commit
c7c4d8061e
101
msg.go
101
msg.go
|
@ -22,7 +22,7 @@ import (
|
|||
"time"
|
||||
"strconv"
|
||||
"encoding/base64"
|
||||
"encoding/base32"
|
||||
"encoding/base32"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
|
@ -76,14 +76,14 @@ var Rr_str = map[uint16]string{
|
|||
TypeLOC: "LOC",
|
||||
TypeOPT: "OPT",
|
||||
TypeDS: "DS",
|
||||
TypeIPSECKEY: "IPSECKEY",
|
||||
TypeIPSECKEY: "IPSECKEY",
|
||||
TypeSSHFP: "SSHFP",
|
||||
TypeRRSIG: "RRSIG",
|
||||
TypeNSEC: "NSEC",
|
||||
TypeDNSKEY: "DNSKEY",
|
||||
TypeNSEC3: "NSEC3",
|
||||
TypeNSEC3PARAM: "NSEC3PARAM",
|
||||
TypeTALINK: "TALINK",
|
||||
TypeTALINK: "TALINK",
|
||||
TypeSPF: "SPF",
|
||||
TypeTKEY: "TKEY", // Meta RR
|
||||
TypeTSIG: "TSIG", // Meta RR
|
||||
|
@ -147,6 +147,7 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
|
|||
|
||||
// Each dot ends a segment of the name.
|
||||
// We trade each dot byte for a length byte.
|
||||
// Except for escaped dots (\.), which are normal dots.
|
||||
// There is also a trailing zero.
|
||||
// Check that we have all the space we need.
|
||||
tot := len(s) + 1
|
||||
|
@ -156,22 +157,32 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
|
|||
|
||||
// Emit sequence of counted strings, chopping at dots.
|
||||
begin := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '.' {
|
||||
if i-begin >= 1<<6 { // top two bits of length must be clear
|
||||
return len(msg), false
|
||||
}
|
||||
msg[off] = byte(i - begin)
|
||||
off++
|
||||
for j := begin; j < i; j++ {
|
||||
msg[off] = s[j]
|
||||
off++
|
||||
}
|
||||
begin = i + 1
|
||||
bs := []byte(s)
|
||||
ls := len(bs)
|
||||
for i := 0; i < ls; i++ {
|
||||
if bs[i] == '\\' {
|
||||
for j := i; j < len(s)-1; j++ {
|
||||
bs[j] = bs[j+1]
|
||||
}
|
||||
ls--
|
||||
continue
|
||||
}
|
||||
|
||||
if bs[i] == '.' {
|
||||
if i-begin >= 1<<6 { // top two bits of length must be clear
|
||||
return len(msg), false
|
||||
}
|
||||
msg[off] = byte(i - begin)
|
||||
off++
|
||||
for j := begin; j < i; j++ {
|
||||
msg[off] = bs[j]
|
||||
off++
|
||||
}
|
||||
begin = i + 1
|
||||
}
|
||||
}
|
||||
// Root label is special
|
||||
if s == "." {
|
||||
if string(bs) == "." {
|
||||
return off, true
|
||||
}
|
||||
msg[off] = 0
|
||||
|
@ -367,39 +378,39 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
|
|||
default:
|
||||
//fmt.Fprintf(os.Stderr, "dns: unknown packing string tag %v", f.Tag)
|
||||
return len(msg), false
|
||||
case "base32":
|
||||
b32, err := packBase32([]byte(s))
|
||||
case "base32":
|
||||
b32, err := packBase32([]byte(s))
|
||||
if err != nil {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing base32")
|
||||
return len(msg), false
|
||||
}
|
||||
copy(msg[off:off+len(b32)], b32)
|
||||
off += len(b32)
|
||||
copy(msg[off:off+len(b32)], b32)
|
||||
off += len(b32)
|
||||
case "base64":
|
||||
b64, err := packBase64([]byte(s))
|
||||
b64, err := packBase64([]byte(s))
|
||||
if err != nil {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing base64")
|
||||
return len(msg), false
|
||||
}
|
||||
copy(msg[off:off+len(b64)], b64)
|
||||
off += len(b64)
|
||||
/*
|
||||
b64len := base64.StdEncoding.DecodedLen(len(s))
|
||||
_, err := base64.StdEncoding.Decode(msg[off:off+b64len], []byte(s))
|
||||
if err != nil {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing base64")
|
||||
return len(msg), false
|
||||
}
|
||||
off += b64len
|
||||
*/
|
||||
copy(msg[off:off+len(b64)], b64)
|
||||
off += len(b64)
|
||||
/*
|
||||
b64len := base64.StdEncoding.DecodedLen(len(s))
|
||||
_, err := base64.StdEncoding.Decode(msg[off:off+b64len], []byte(s))
|
||||
if err != nil {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing base64")
|
||||
return len(msg), false
|
||||
}
|
||||
off += b64len
|
||||
*/
|
||||
case "domain-name":
|
||||
off, ok = packDomainName(s, msg, off)
|
||||
if !ok {
|
||||
//fmt.Fprintf(os.Stderr, "dns: overflow packing domain-name")
|
||||
return len(msg), false
|
||||
}
|
||||
case "size-hex":
|
||||
fallthrough;
|
||||
case "size-hex":
|
||||
fallthrough
|
||||
case "hex":
|
||||
// There is no length encoded here
|
||||
h, e := hex.DecodeString(s)
|
||||
|
@ -604,8 +615,8 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||
consumed = 2 // Algorithm(1) + Type(1)
|
||||
case "RR_NSEC3PARAM":
|
||||
consumed = 5 // Hash(1) + Flags(1) + Iterations(2) + SaltLength(1)
|
||||
case "RR_RFC3597":
|
||||
fallthrough; // Rest is the unknown data
|
||||
case "RR_RFC3597":
|
||||
fallthrough // Rest is the unknown data
|
||||
default:
|
||||
consumed = 0 // return len(msg), false?
|
||||
}
|
||||
|
@ -636,7 +647,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||
//fmt.Fprintf(os.Stderr, "dns: failure unpacking domain-name")
|
||||
return len(msg), false
|
||||
}
|
||||
case "size-base32":
|
||||
case "size-base32":
|
||||
var size int
|
||||
switch val.Type().Name() {
|
||||
case "RR_NSEC3":
|
||||
|
@ -645,15 +656,15 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||
name := val.FieldByName("HashLength")
|
||||
size = int(name.(*reflect.UintValue).Get())
|
||||
}
|
||||
}
|
||||
}
|
||||
if off+size > len(msg) {
|
||||
//fmt.Fprintf(os.Stderr, "dns: failure unpacking size-base32 string")
|
||||
return len(msg), false
|
||||
}
|
||||
s = unpackBase32(msg[off : off+size])
|
||||
off += size
|
||||
case "size-hex":
|
||||
// a "size" string, but a it must be encoded in hex in the string
|
||||
case "size-hex":
|
||||
// a "size" string, but a it must be encoded in hex in the string
|
||||
var size int
|
||||
switch val.Type().Name() {
|
||||
case "RR_NSEC3":
|
||||
|
@ -665,7 +676,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||
name := val.FieldByName("HashLength")
|
||||
size = int(name.(*reflect.UintValue).Get())
|
||||
}
|
||||
}
|
||||
}
|
||||
if off+size > len(msg) {
|
||||
//fmt.Fprintf(os.Stderr, "dns: failure unpacking hex-size string")
|
||||
return len(msg), false
|
||||
|
@ -800,11 +811,11 @@ func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) {
|
|||
// make an rr of that type and re-unpack.
|
||||
// again inefficient but doesn't need to be fast.
|
||||
mk, known := rr_mk[int(h.Rrtype)]
|
||||
if !known {
|
||||
rr = new(RR_RFC3597)
|
||||
if !known {
|
||||
rr = new(RR_RFC3597)
|
||||
} else {
|
||||
rr = mk()
|
||||
}
|
||||
rr = mk()
|
||||
}
|
||||
off, ok = unpackStruct(rr, msg, off0)
|
||||
if off != end {
|
||||
return &h, end, true
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
"crypto/rsa"
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ Activate: 20110109154937`
|
|||
k.Hdr.Rrtype = TypeDNSKEY
|
||||
k.Hdr.Class = ClassINET
|
||||
k.Hdr.Name = "miek.nl."
|
||||
k.Hdr.Ttl = 3600
|
||||
k.Hdr.Ttl = 3600
|
||||
k.Protocol = 3
|
||||
k.Flags = 256
|
||||
p, _ := k.PrivateKeySetString(a)
|
||||
|
@ -92,47 +92,66 @@ Activate: 20110109154937`
|
|||
t.Fail()
|
||||
}
|
||||
|
||||
soa := new(RR_SOA)
|
||||
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
||||
soa.Ns = "open.nlnetlabs.nl."
|
||||
soa.Mbox = "miekg.atoom.net."
|
||||
soa.Serial = 1293945905
|
||||
soa.Refresh = 14400
|
||||
soa.Retry = 3600
|
||||
soa.Expire = 604800
|
||||
soa.Minttl = 86400
|
||||
soa := new(RR_SOA)
|
||||
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
||||
soa.Ns = "open.nlnetlabs.nl."
|
||||
soa.Mbox = "miekg.atoom.net."
|
||||
soa.Serial = 1293945905
|
||||
soa.Refresh = 14400
|
||||
soa.Retry = 3600
|
||||
soa.Expire = 604800
|
||||
soa.Minttl = 86400
|
||||
|
||||
sig := new(RR_RRSIG)
|
||||
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
||||
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
||||
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
||||
sig.KeyTag = k.KeyTag()
|
||||
sig.SignerName = k.Hdr.Name
|
||||
sig.Algorithm = k.Algorithm
|
||||
sig := new(RR_RRSIG)
|
||||
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
||||
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
||||
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
||||
sig.KeyTag = k.KeyTag()
|
||||
sig.SignerName = k.Hdr.Name
|
||||
sig.Algorithm = k.Algorithm
|
||||
|
||||
sig.Sign(p, []RR{soa})
|
||||
fmt.Printf("%v\n%v\n%v\n", k, soa, sig)
|
||||
sig.Sign(p, []RR{soa})
|
||||
fmt.Printf("%v\n%v\n%v\n", k, soa, sig)
|
||||
}
|
||||
|
||||
func TestA(t *testing.T) {
|
||||
a := new(RR_A)
|
||||
a.Hdr = RR_Header{"miek.nl.", TypeA, ClassINET, 14400, 0}
|
||||
a.A = net.ParseIP("192.168.1.1")
|
||||
str := a.String()
|
||||
if str != "miek.nl.\t14400\tIN\tA\t192.168.1.1" {
|
||||
t.Log(str)
|
||||
t.Fail()
|
||||
}
|
||||
a := new(RR_A)
|
||||
a.Hdr = RR_Header{"miek.nl.", TypeA, ClassINET, 14400, 0}
|
||||
a.A = net.ParseIP("192.168.1.1")
|
||||
str := a.String()
|
||||
if str != "miek.nl.\t14400\tIN\tA\t192.168.1.1" {
|
||||
t.Log(str)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuadA(t *testing.T) {
|
||||
a := new(RR_AAAA)
|
||||
a.Hdr = RR_Header{"miek.nl.", TypeAAAA, ClassINET, 14400, 0}
|
||||
a.AAAA = net.ParseIP("::1")
|
||||
str := a.String()
|
||||
if str != "miek.nl.\t14400\tIN\tAAAA\t::1" {
|
||||
t.Log(str)
|
||||
a := new(RR_AAAA)
|
||||
a.Hdr = RR_Header{"miek.nl.", TypeAAAA, ClassINET, 14400, 0}
|
||||
a.AAAA = net.ParseIP("::1")
|
||||
str := a.String()
|
||||
if str != "miek.nl.\t14400\tIN\tAAAA\t::1" {
|
||||
t.Log(str)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDotInName(t *testing.T) {
|
||||
buf := make([]byte, 20)
|
||||
packDomainName("aa\\.bb.nl", buf, 0)
|
||||
// index 3 must be a real dot
|
||||
if buf[3] != '.' {
|
||||
t.Log("Dot should be a real dot")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if buf[6] != 2 {
|
||||
t.Log("This must have the value 2")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
dom, _, ok := unpackDomainName(buf, 0)
|
||||
// printing it should yield the backspace again
|
||||
println(dom)
|
||||
println(ok)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue