Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SVCB #1067

Merged
merged 92 commits into from
Oct 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5b07e30
Implement SVCB
DesWurstes Dec 29, 2019
1975c09
Fix serialization and deserialization of double quotes
DesWurstes Dec 31, 2019
3206314
More effort (?)
DesWurstes Apr 2, 2020
4121dea
DEBUG
DesWurstes Apr 2, 2020
d8122ee
_
DesWurstes Apr 3, 2020
4059142
Presentation format serialization/deserialization
DesWurstes Apr 7, 2020
8073e20
_
DesWurstes Apr 7, 2020
0531af9
Progress on presentation format parse & write
DesWurstes Apr 7, 2020
c3f3c2e
_
DesWurstes Apr 7, 2020
6129591
Finish parsing presentation format
DesWurstes Apr 7, 2020
713d753
Regenerate
DesWurstes Apr 7, 2020
769f523
Pack unpack
DesWurstes Apr 9, 2020
d928295
Move to svcb.go
DesWurstes Apr 20, 2020
5029d5c
:bug:
DesWurstes Apr 20, 2020
8c8d6b1
Definitions
DesWurstes Apr 21, 2020
4e4acfb
TypeHTTPSSVC
DesWurstes Apr 21, 2020
9f14891
Generated
DesWurstes Apr 21, 2020
53c0864
Goodbye lenient functions
DesWurstes Apr 21, 2020
21751e1
Encode/decode
DesWurstes Apr 22, 2020
12cbdca
Experimental svc
DesWurstes Apr 22, 2020
1b35a57
Read method
DesWurstes Apr 22, 2020
33283d1
Implement some of the methods, use trick...
DesWurstes Apr 22, 2020
7d91bcb
Add SVC_LOCAL methods, reorder, remove alpn value, bugs
DesWurstes Apr 22, 2020
37acfc5
Errors
DesWurstes Apr 22, 2020
79ce0d9
Alpn, make it build
DesWurstes Apr 22, 2020
ecc18f3
Correct testsuite
DesWurstes Apr 22, 2020
079e8b3
Fully implement parser
DesWurstes Apr 23, 2020
4e086ce
Simplify and document
DesWurstes Apr 23, 2020
72c7af4
Attempt to fix fuzzer
DesWurstes Apr 23, 2020
6c9e4d9
A bug and change type values to match @ghedo's implementation
DesWurstes Apr 23, 2020
1a22c1d
IP bug
DesWurstes Apr 23, 2020
2b6a4a2
Check for strictly increasing keys as required
DesWurstes Apr 23, 2020
4eb7dd5
Don't panic on invalid alpn
DesWurstes Apr 24, 2020
836765d
Redundant check, don't modify original array
DesWurstes Apr 24, 2020
00868aa
Size calculation
DesWurstes Apr 24, 2020
5d08839
Fix the fuzzer, match the style
DesWurstes Apr 26, 2020
40c1da5
65535 is reserved too, don't delay errors
DesWurstes Apr 26, 2020
073eecf
Check keyNNN, check for aliasform having values
DesWurstes Apr 27, 2020
21af410
IPvNHint is an array
DesWurstes Apr 27, 2020
f9ba9af
Fix ipvNHint
DesWurstes Apr 28, 2020
f9b23b7
Rename everything
DesWurstes Apr 28, 2020
e5d6084
Unrecognized keys according to the updated specification
DesWurstes May 1, 2020
0740374
Skip zero-length structs in generators. Fix CI
DesWurstes May 1, 2020
a338499
Doc cleanup
DesWurstes May 1, 2020
b2a1b6b
Off by one
DesWurstes May 1, 2020
3f6057f
Add parse tests
DesWurstes May 2, 2020
f218404
Check if private key doesn't collide with known key, invalid tests
DesWurstes May 2, 2020
5eb0c16
Disallow IPv4 as IPv6. More tests.
DesWurstes May 2, 2020
9eadb35
Style fixes
DesWurstes May 3, 2020
9d805ac
More consistency, more tests
DesWurstes May 3, 2020
b49878c
:bug: Deep copy as in the documentation
DesWurstes May 3, 2020
7a78b33
Make tests readable
DesWurstes May 3, 2020
ec9e6df
Move valid parse tests to different file
DesWurstes May 4, 2020
131f50b
:bug: One of previous commits not fully committed
DesWurstes May 4, 2020
6e06a08
Test binary single value encoding/decoding and full encode/decode
DesWurstes May 4, 2020
b6df121
Add worst-case grows to builders, :bug: Wrong visible character range…
DesWurstes May 4, 2020
5972d34
Testing improvements
DesWurstes May 4, 2020
c8af8d7
Doc update only
DesWurstes May 4, 2020
bd6df17
Document worst case allocations
DesWurstes May 6, 2020
7b24238
Redundant IP copy, consistent IPv6 behavior, fix deep copy
DesWurstes May 8, 2020
6f6931c
isDuplicate for SVCB
DesWurstes May 9, 2020
424d529
Optimizations
DesWurstes May 10, 2020
7689d80
echoconfig
DesWurstes May 13, 2020
a0e148f
Svc => SVCB
DesWurstes May 13, 2020
28d989e
Fix CI
DesWurstes May 14, 2020
d98ceea
Regenerate after REBASE (2)
DesWurstes May 15, 2020
69c1108
Rename svc, use escapeByte.
DesWurstes May 20, 2020
d6d8163
Fix parsing whitespaces between quotes, rename ECHOHOConfig
DesWurstes May 24, 2020
7e74b9b
resolve
DesWurstes Jun 4, 2020
39ad757
a little more
DesWurstes Jun 4, 2020
f1eeef2
HTTPSSVC -> HTTPS
DesWurstes Jun 13, 2020
d65a30a
Use new values
DesWurstes Jun 30, 2020
1a41149
mandatory code
DesWurstes Jul 6, 2020
f8239f9
Resolve comments
DesWurstes Jul 21, 2020
e4b3be1
Refactor 1
DesWurstes Jul 26, 2020
e751007
Refactor 2
DesWurstes Jul 26, 2020
05fe81d
Refactor 3
DesWurstes Jul 26, 2020
7ea3267
Refactor 4
DesWurstes Jul 26, 2020
07a20b1
Refactor 5
DesWurstes Jul 26, 2020
ea0812c
Refactor 6
DesWurstes Jul 26, 2020
278d221
Refactor 7
DesWurstes Jul 26, 2020
6976c49
Test remove parsing
DesWurstes Jul 26, 2020
133d88c
Error messages
DesWurstes Jul 26, 2020
6b92114
Rewrite two estimate comments
DesWurstes Jul 28, 2020
2ca90e6
parse shouldn't modify original array :bug:
DesWurstes Jul 28, 2020
6b636a5
Remove two unneeded comments
DesWurstes Aug 5, 2020
7c0f78e
Address review comments
DesWurstes Aug 6, 2020
297d02d
Simplify argument duplication as per tmthrgd's suggestion
DesWurstes Sep 18, 2020
40bca2d
Rewrite ECHConfig and address the review
DesWurstes Sep 27, 2020
dae3391
Remove the optional tab
DesWurstes Sep 27, 2020
59c9584
Add To4() Check
DesWurstes Sep 27, 2020
5cfc4ab
More cleanup and fix mandatory not sorting bug
DesWurstes Sep 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions duplicate_generate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions duplicate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,39 @@ func TestDuplicateTXT(t *testing.T) {
}
}

func TestDuplicateSVCB(t *testing.T) {
a1, _ := NewRR(`example.com. 3600 IN SVCB 1 . ipv6hint=1::3:3:3:3 key65300=\254\032\030\000\ \043,\;`)
a2, _ := NewRR(`example.com. 3600 IN SVCB 1 . ipv6hint=1:0::3:3:3:3 key65300="\254\ \030\000 +\,;"`)

if !IsDuplicate(a1, a2) {
t.Errorf("expected %s/%s to be duplicates, but got false", a1.String(), a2.String())
}

a2, _ = NewRR(`example.com. 3600 IN SVCB 1 . ipv6hint=1::3:3:3:3 key65300="\255\ \030\000 +\,;"`)

if IsDuplicate(a1, a2) {
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
}

a1, _ = NewRR(`example.com. 3600 IN SVCB 1 . ipv6hint=1::3:3:3:3`)

if IsDuplicate(a1, a2) {
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
}

a2, _ = NewRR(`example.com. 3600 IN SVCB 1 . ipv4hint=1.1.1.1`)

if IsDuplicate(a1, a2) {
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
}

a1, _ = NewRR(`example.com. 3600 IN SVCB 1 . ipv4hint=1.1.1.1,1.0.2.1`)

if IsDuplicate(a1, a2) {
t.Errorf("expected %s/%s not to be duplicates, but got true", a1.String(), a2.String())
}
}

func TestDuplicateOwner(t *testing.T) {
a1, _ := NewRR("www.example.org. IN A 127.0.0.1")
a2, _ := NewRR("www.example.org. IN A 127.0.0.1")
Expand Down
7 changes: 7 additions & 0 deletions msg_generate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions msg_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/binary"
"encoding/hex"
"net"
"sort"
"strings"
)

Expand Down Expand Up @@ -612,6 +613,65 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
return off, nil
}

func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
var xs []SVCBKeyValue
var code uint16
var length uint16
var err error
for off < len(msg) {
code, off, err = unpackUint16(msg, off)
if err != nil {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
length, off, err = unpackUint16(msg, off)
if err != nil || off+int(length) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
e := makeSVCBKeyValue(SVCBKey(code))
if e == nil {
return nil, len(msg), &Error{err: "bad SVCB key"}
}
if err := e.unpack(msg[off : off+int(length)]); err != nil {
return nil, len(msg), err
}
if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
}
xs = append(xs, e)
off += int(length)
}
return xs, off, nil
}

func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
pairs = append([]SVCBKeyValue(nil), pairs...)
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].Key() < pairs[j].Key()
})
prev := svcb_RESERVED
for _, el := range pairs {
if el.Key() == prev {
return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
}
prev = el.Key()
packed, err := el.pack()
if err != nil {
return len(msg), err
}
off, err = packUint16(uint16(el.Key()), msg, off)
if err != nil {
return len(msg), &Error{err: "overflow packing SVCB"}
}
off, err = packUint16(uint16(len(packed)), msg, off)
if err != nil || off+len(packed) > len(msg) {
return len(msg), &Error{err: "overflow packing SVCB"}
}
copy(msg[off:off+len(packed)], packed)
off += len(packed)
}
return off, nil
}

func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
var (
servers []string
Expand Down
64 changes: 64 additions & 0 deletions parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,70 @@ func TestParseCSYNC(t *testing.T) {
}
}

func TestParseSVCB(t *testing.T) {
svcbs := map[string]string{
`example.com. 3600 IN SVCB 0 cloudflare.com.`: `example.com. 3600 IN SVCB 0 cloudflare.com.`,
`example.com. 3600 IN SVCB 65000 cloudflare.com. alpn=h2 ipv4hint=3.4.3.2`: `example.com. 3600 IN SVCB 65000 cloudflare.com. alpn="h2" ipv4hint="3.4.3.2"`,
`example.com. 3600 IN SVCB 65000 cloudflare.com. key65000=4\ 3 key65001="\" " key65002 key65003= key65004="" key65005== key65006==\"\" key65007=\254 key65008=\032`: `example.com. 3600 IN SVCB 65000 cloudflare.com. key65000="4\ 3" key65001="\"\ " key65002="" key65003="" key65004="" key65005="=" key65006="=\"\"" key65007="\254" key65008="\ "`,
}
for s, o := range svcbs {
rr, err := NewRR(s)
if err != nil {
t.Error("failed to parse RR: ", err)
continue
}
if rr.String() != o {
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", s, o, rr.String())
}
}
}

func TestParseBadSVCB(t *testing.T) {
header := `example.com. 3600 IN HTTPS `
evils := []string{
`0 . no-default-alpn`, // aliasform
`65536 . no-default-alpn`, // bad priority
`1 ..`, // bad domain
`1 . no-default-alpn=1`, // value illegal
`1 . key`, // invalid key
`1 . key=`, // invalid key
`1 . =`, // invalid key
`1 . ==`, // invalid key
`1 . =a`, // invalid key
`1 . ""`, // invalid key
`1 . ""=`, // invalid key
`1 . "a"`, // invalid key
`1 . "a"=`, // invalid key
`1 . key1=`, // we know that key
`1 . key65535`, // key reserved
`1 . key065534`, // key can't be padded
`1 . key65534="f`, // unterminated value
`1 . key65534="`, // unterminated value
`1 . key65534=\2`, // invalid numberic escape
`1 . key65534=\24`, // invalid numberic escape
`1 . key65534=\256`, // invalid numberic escape
`1 . key65534=\`, // invalid numberic escape
`1 . key65534=""alpn`, // zQuote ending needs whitespace
`1 . key65534="a"alpn`, // zQuote ending needs whitespace
`1 . ipv6hint=1.1.1.1`, // not ipv6
`1 . ipv6hint=1:1:1:1`, // not ipv6
`1 . ipv6hint=a`, // not ipv6
`1 . ipv4hint=1.1.1.1.1`, // not ipv4
`1 . ipv4hint=::fc`, // not ipv4
`1 . ipv4hint=..11`, // not ipv4
`1 . ipv4hint=a`, // not ipv4
`1 . port=`, // empty port
`1 . echconfig=YUd`, // bad base64
}
for _, o := range evils {
_, err := NewRR(header + o)
if err == nil {
t.Error("failed to reject invalid RR: ", header+o)
continue
}
}
}

func TestParseBadNAPTR(t *testing.T) {
// Should look like: mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 "S" "SIP+D2U" "" _sip._udp.mplus.ims.vodafone.com.
naptr := `mplus.ims.vodafone.com. 3600 IN NAPTR 10 100 S SIP+D2U _sip._udp.mplus.ims.vodafone.com.`
Expand Down
Loading