mirror of
https://github.com/golang/net.git
synced 2026-03-31 10:27:08 +09:00
dns/dnsmessage: correctly handle multiple and >255 byte TXT records
Previously, we only accepted a single string for TXT records and then chunked it into 255 byte segments. This is wrong. TXT records are a sequence of strings, each up to 255 bytes. Updates golang/go#24288 Change-Id: Ib2c085ec127ccecf0c7bda930100b667cabc1f4b Reviewed-on: https://go-review.googlesource.com/100196 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
803fdb99c0
commit
892bf7b0c6
@@ -90,6 +90,7 @@ var (
|
||||
errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)")
|
||||
errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
|
||||
errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)")
|
||||
errStringTooLong = errors.New("character string exceeds maximum length (255)")
|
||||
)
|
||||
|
||||
// Internal constants.
|
||||
@@ -218,6 +219,7 @@ func (h *header) count(sec section) uint16 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// pack appends the wire format of the header to msg.
|
||||
func (h *header) pack(msg []byte) []byte {
|
||||
msg = packUint16(msg, h.id)
|
||||
msg = packUint16(msg, h.bits)
|
||||
@@ -280,6 +282,7 @@ type ResourceBody interface {
|
||||
realType() Type
|
||||
}
|
||||
|
||||
// pack appends the wire format of the Resource to msg.
|
||||
func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
if r.Body == nil {
|
||||
return msg, errNilResouceBody
|
||||
@@ -1311,9 +1314,10 @@ type ResourceHeader struct {
|
||||
Length uint16
|
||||
}
|
||||
|
||||
// pack packs all of the fields in a ResourceHeader except for the length. The
|
||||
// length bytes are returned as a slice so they can be filled in after the rest
|
||||
// of the Resource has been packed.
|
||||
// pack appends the wire format of the ResourceHeader to oldMsg.
|
||||
//
|
||||
// The bytes where length was packed are returned as a slice so they can be
|
||||
// updated after the rest of the Resource has been packed.
|
||||
func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, length []byte, err error) {
|
||||
msg = oldMsg
|
||||
if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil {
|
||||
@@ -1385,6 +1389,7 @@ func skipResource(msg []byte, off int) (int, error) {
|
||||
return newOff, nil
|
||||
}
|
||||
|
||||
// packUint16 appends the wire format of field to msg.
|
||||
func packUint16(msg []byte, field uint16) []byte {
|
||||
return append(msg, byte(field>>8), byte(field))
|
||||
}
|
||||
@@ -1403,6 +1408,7 @@ func skipUint16(msg []byte, off int) (int, error) {
|
||||
return off + uint16Len, nil
|
||||
}
|
||||
|
||||
// packType appends the wire format of field to msg.
|
||||
func packType(msg []byte, field Type) []byte {
|
||||
return packUint16(msg, uint16(field))
|
||||
}
|
||||
@@ -1416,6 +1422,7 @@ func skipType(msg []byte, off int) (int, error) {
|
||||
return skipUint16(msg, off)
|
||||
}
|
||||
|
||||
// packClass appends the wire format of field to msg.
|
||||
func packClass(msg []byte, field Class) []byte {
|
||||
return packUint16(msg, uint16(field))
|
||||
}
|
||||
@@ -1429,6 +1436,7 @@ func skipClass(msg []byte, off int) (int, error) {
|
||||
return skipUint16(msg, off)
|
||||
}
|
||||
|
||||
// packUint32 appends the wire format of field to msg.
|
||||
func packUint32(msg []byte, field uint32) []byte {
|
||||
return append(
|
||||
msg,
|
||||
@@ -1454,17 +1462,16 @@ func skipUint32(msg []byte, off int) (int, error) {
|
||||
return off + uint32Len, nil
|
||||
}
|
||||
|
||||
func packText(msg []byte, field string) []byte {
|
||||
for len(field) > 0 {
|
||||
l := len(field)
|
||||
if l > 255 {
|
||||
l = 255
|
||||
}
|
||||
msg = append(msg, byte(l))
|
||||
msg = append(msg, field[:l]...)
|
||||
field = field[l:]
|
||||
// packText appends the wire format of field to msg.
|
||||
func packText(msg []byte, field string) ([]byte, error) {
|
||||
l := len(field)
|
||||
if l > 255 {
|
||||
return nil, errStringTooLong
|
||||
}
|
||||
return msg
|
||||
msg = append(msg, byte(l))
|
||||
msg = append(msg, field...)
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func unpackText(msg []byte, off int) (string, int, error) {
|
||||
@@ -1490,6 +1497,7 @@ func skipText(msg []byte, off int) (int, error) {
|
||||
return endOff, nil
|
||||
}
|
||||
|
||||
// packBytes appends the wire format of field to msg.
|
||||
func packBytes(msg []byte, field []byte) []byte {
|
||||
return append(msg, field...)
|
||||
}
|
||||
@@ -1534,7 +1542,7 @@ func (n Name) String() string {
|
||||
return string(n.Data[:n.Length])
|
||||
}
|
||||
|
||||
// pack packs a domain name.
|
||||
// pack appends the wire format of the Name to msg.
|
||||
//
|
||||
// Domain names are a sequence of counted strings split at the dots. They end
|
||||
// with a zero-length string. Compression can be used to reuse domain suffixes.
|
||||
@@ -1716,6 +1724,7 @@ type Question struct {
|
||||
Class Class
|
||||
}
|
||||
|
||||
// pack appends the wire format of the Question to msg.
|
||||
func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
msg, err := q.Name.pack(msg, compression, compressionOff)
|
||||
if err != nil {
|
||||
@@ -1796,6 +1805,7 @@ func (r *CNAMEResource) realType() Type {
|
||||
return TypeCNAME
|
||||
}
|
||||
|
||||
// pack appends the wire format of the CNAMEResource to msg.
|
||||
func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return r.CNAME.pack(msg, compression, compressionOff)
|
||||
}
|
||||
@@ -1818,6 +1828,7 @@ func (r *MXResource) realType() Type {
|
||||
return TypeMX
|
||||
}
|
||||
|
||||
// pack appends the wire format of the MXResource to msg.
|
||||
func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg = packUint16(msg, r.Pref)
|
||||
@@ -1849,6 +1860,7 @@ func (r *NSResource) realType() Type {
|
||||
return TypeNS
|
||||
}
|
||||
|
||||
// pack appends the wire format of the NSResource to msg.
|
||||
func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return r.NS.pack(msg, compression, compressionOff)
|
||||
}
|
||||
@@ -1870,6 +1882,7 @@ func (r *PTRResource) realType() Type {
|
||||
return TypePTR
|
||||
}
|
||||
|
||||
// pack appends the wire format of the PTRResource to msg.
|
||||
func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return r.PTR.pack(msg, compression, compressionOff)
|
||||
}
|
||||
@@ -1901,6 +1914,7 @@ func (r *SOAResource) realType() Type {
|
||||
return TypeSOA
|
||||
}
|
||||
|
||||
// pack appends the wire format of the SOAResource to msg.
|
||||
func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg, err := r.NS.pack(msg, compression, compressionOff)
|
||||
@@ -1953,19 +1967,28 @@ func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
|
||||
|
||||
// A TXTResource is a TXT Resource record.
|
||||
type TXTResource struct {
|
||||
Txt string // Not a domain name.
|
||||
TXT []string
|
||||
}
|
||||
|
||||
func (r *TXTResource) realType() Type {
|
||||
return TypeTXT
|
||||
}
|
||||
|
||||
// pack appends the wire format of the TXTResource to msg.
|
||||
func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return packText(msg, r.Txt), nil
|
||||
oldMsg := msg
|
||||
for _, s := range r.TXT {
|
||||
var err error
|
||||
msg, err = packText(msg, s)
|
||||
if err != nil {
|
||||
return oldMsg, err
|
||||
}
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
|
||||
var txt string
|
||||
txts := make([]string, 0, 1)
|
||||
for n := uint16(0); n < length; {
|
||||
var t string
|
||||
var err error
|
||||
@@ -1977,9 +2000,9 @@ func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error)
|
||||
return TXTResource{}, errCalcLen
|
||||
}
|
||||
n += uint16(len(t)) + 1
|
||||
txt += t
|
||||
txts = append(txts, t)
|
||||
}
|
||||
return TXTResource{txt}, nil
|
||||
return TXTResource{txts}, nil
|
||||
}
|
||||
|
||||
// An SRVResource is an SRV Resource record.
|
||||
@@ -1994,6 +2017,7 @@ func (r *SRVResource) realType() Type {
|
||||
return TypeSRV
|
||||
}
|
||||
|
||||
// pack appends the wire format of the SRVResource to msg.
|
||||
func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg = packUint16(msg, r.Priority)
|
||||
@@ -2035,6 +2059,7 @@ func (r *AResource) realType() Type {
|
||||
return TypeA
|
||||
}
|
||||
|
||||
// pack appends the wire format of the AResource to msg.
|
||||
func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return packBytes(msg, r.A[:]), nil
|
||||
}
|
||||
@@ -2056,6 +2081,7 @@ func (r *AAAAResource) realType() Type {
|
||||
return TypeAAAA
|
||||
}
|
||||
|
||||
// pack appends the wire format of the AAAAResource to msg.
|
||||
func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
return packBytes(msg, r.AAAA[:]), nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -444,7 +445,15 @@ func TestVeryLongTxt(t *testing.T) {
|
||||
Type: TypeTXT,
|
||||
Class: ClassINET,
|
||||
},
|
||||
&TXTResource{loremIpsum},
|
||||
&TXTResource{[]string{
|
||||
"",
|
||||
"",
|
||||
"foo bar",
|
||||
"",
|
||||
"www.example.com",
|
||||
"www.example.com.",
|
||||
strings.Repeat(".", 255),
|
||||
}},
|
||||
}
|
||||
buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0)
|
||||
if err != nil {
|
||||
@@ -468,6 +477,13 @@ func TestVeryLongTxt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTooLongTxt(t *testing.T) {
|
||||
rb := TXTResource{[]string{strings.Repeat(".", 256)}}
|
||||
if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong {
|
||||
t.Errorf("Packing TXTRecord with 256 character string: got err = %v, want = %v", err, errStringTooLong)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartAppends(t *testing.T) {
|
||||
buf := make([]byte, 2, 514)
|
||||
wantBuf := []byte{4, 44}
|
||||
@@ -1084,7 +1100,7 @@ func largeTestMsg() Message {
|
||||
Type: TypeTXT,
|
||||
Class: ClassINET,
|
||||
},
|
||||
&TXTResource{"So Long, and Thanks for All the Fish"},
|
||||
&TXTResource{[]string{"So Long, and Thanks for All the Fish"}},
|
||||
},
|
||||
{
|
||||
ResourceHeader{
|
||||
@@ -1092,139 +1108,8 @@ func largeTestMsg() Message {
|
||||
Type: TypeTXT,
|
||||
Class: ClassINET,
|
||||
},
|
||||
&TXTResource{"Hamster Huey and the Gooey Kablooie"},
|
||||
&TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const loremIpsum = `
|
||||
Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro
|
||||
nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos,
|
||||
magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas
|
||||
regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei
|
||||
nam ipsum assentior.
|
||||
|
||||
Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum
|
||||
facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque
|
||||
no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem
|
||||
reformidans et. Qui ei eros porro reformidans, ius suas veritus
|
||||
torquatos ex. Mea te facer alterum consequat.
|
||||
|
||||
Soleat torquatos democritum sed et, no mea congue appareat, facer
|
||||
aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet
|
||||
phaedrum ad nam. Ea detracto verterem liberavisse has, delectus
|
||||
suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis
|
||||
honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum
|
||||
mollis.
|
||||
|
||||
Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad
|
||||
vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque
|
||||
vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum
|
||||
dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut
|
||||
pro, vel ne saepe senserit consetetur.
|
||||
|
||||
Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no
|
||||
enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum
|
||||
sententiae deterruisset ut. At suas timeam euismod cum, offendit
|
||||
appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam
|
||||
accusata intellegebat, noluisse instructior sea id. Nec te nonumes
|
||||
habemus appellantur, quis dignissim vituperata eu nam.
|
||||
|
||||
At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet
|
||||
iisque an mea. Per eu dicant ponderum accommodare. Pri alienum
|
||||
placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea
|
||||
eligendi disputationi. Ius no tation everti impedit, ei magna quidam
|
||||
mediocritatem pri.
|
||||
|
||||
Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam,
|
||||
ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo
|
||||
has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut
|
||||
iudico albucius his.
|
||||
|
||||
Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue
|
||||
dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse,
|
||||
an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At
|
||||
vis dicant abhorreant, utinam forensibus nec ne, mei te docendi
|
||||
consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae
|
||||
usu, dicit graeco disputando id has.
|
||||
|
||||
Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec
|
||||
torquatos sadipscing ei, ancillae molestie per in. Malis principes duo
|
||||
ea, usu liber postulant ei.
|
||||
|
||||
Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta
|
||||
feugiat duo. Congue option meliore ex qui, noster invenire appellantur
|
||||
ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an
|
||||
probo minimum, et nam illud falli tempor.
|
||||
|
||||
Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens
|
||||
tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat
|
||||
tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri.
|
||||
|
||||
Ad oratio blandit aliquando pro. Vis et dolorum rationibus
|
||||
philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et,
|
||||
ne qui nisl verear saperet, vel te quaestio forensibus. Per odio
|
||||
option delenit an. Alii placerat has no, in pri nihil platonem
|
||||
cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea
|
||||
an.
|
||||
|
||||
Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat
|
||||
accusam mea et. Elitr labitur albucius et pri, an labore feugait mel.
|
||||
Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no
|
||||
error volumus scripserit. In pro paulo iudico, quo ei dolorem
|
||||
verterem, affert fabellas dissentiet ea vix.
|
||||
|
||||
Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi
|
||||
salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at
|
||||
nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit
|
||||
utroque vis, ex equidem detraxit temporibus has.
|
||||
|
||||
Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas
|
||||
pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad
|
||||
mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata
|
||||
interesset. Mel sapientem prodesset abhorreant et, oblique suscipit
|
||||
eam id.
|
||||
|
||||
An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens
|
||||
inciderint no sea. Ea persius maluisset vix, ne vim appellantur
|
||||
instructior, consul quidam definiebas pri id. Cum integre feugiat
|
||||
pericula in, ex sed persius similique, mel ne natum dicit percipitur.
|
||||
|
||||
Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore
|
||||
neglegentur, mei tincidunt percipitur ei. Pro ad simul integre
|
||||
rationibus. Eu vel alii honestatis definitiones, mea no nonumy
|
||||
reprehendunt.
|
||||
|
||||
Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix
|
||||
adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat
|
||||
duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum
|
||||
debitis nostrum no, ut vel aliquid vivendo.
|
||||
|
||||
Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi.
|
||||
Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo
|
||||
dolore impedit id eam, et aeque feugait assentior has. Quando sensibus
|
||||
nec ex. Possit sensibus pri ad, unum mutat periculis cu vix.
|
||||
|
||||
Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit
|
||||
sonet tempor. No per solet aeterno deseruisse. Petentium salutandi
|
||||
definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi
|
||||
vis, modus offendit omittantur te mel.
|
||||
|
||||
Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam
|
||||
melius conceptam est ne, quo in minimum apeirian delicata, ut ius
|
||||
porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu
|
||||
his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te
|
||||
per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis
|
||||
ad idque fabellas intellegebat.
|
||||
|
||||
Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut,
|
||||
mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne
|
||||
alia corpora invenire, alia prima soleat te cum. Eleifend posidonium
|
||||
nam at.
|
||||
|
||||
Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril
|
||||
discere. Nec civibus officiis dissentiunt ex, est te liber ludus
|
||||
elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit
|
||||
comprehensam, nam te inermis delectus, saepe inermis senserit.
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user