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

Handle packing of empty RDATA correctly for EDNS0_EXPIRE (Resolves #1292) #1293

Merged
merged 5 commits into from
Mar 12, 2022

Conversation

dmavrommatis
Copy link
Contributor

Issue explained in #1292

@miekg
Copy link
Owner

miekg commented Sep 4, 2021

Thanks. Could you provide a better description in your commit. uint32 was plain wrong? Where in the RFC do I need to look? Etc.

@dmavrommatis
Copy link
Contributor Author

dmavrommatis commented Sep 6, 2021

I've documented the bug and thought process in the issue mentioned. I've also changed the description in the commit to also mention the RFC and the issue:

As per RFC7314 the Expire Option in queries should be zero-length. In the current implementation the field is uint32 which always instatiates 4bytes for that field when packing to wire format.
For that reason we change the field to []uint8 so it can support 0-length and 4-byte
length option data.

…iekg#1292)

As per [RFC7134](https://datatracker.ietf.org/doc/html/rfc7314#section-2) the Expire
Option in queries should be zero-length. In the current implementation the field is
uint32 which always instatiates 4bytes for that field when packing to wire format.
For that reason we change the field to []uint8 so it can support 0-length and 4-byte
length option data.
edns.go Outdated Show resolved Hide resolved
edns.go Outdated Show resolved Hide resolved
edns.go Outdated Show resolved Hide resolved
@dmavrommatis
Copy link
Contributor Author

@miekg thanks for the review; I've addressed the comments. Please take a look again!

edns.go Outdated Show resolved Hide resolved
edns.go Outdated Show resolved Hide resolved
@tmthrgd
Copy link
Collaborator

tmthrgd commented Oct 28, 2021

(Apologies for the absence on GitHub).

RFC 7314 says "This is done by adding a zero-length EDNS EXPIRE option to the options field of the OPT record when the query is made." so a zero length option is valid and something we should be handling. There's nothing in the RFC to say that the 32-bit value zero is reserved so we have to persist this somehow.

This PR isn't backward compatible though so we shouldn't merge as-is. What we could do is hang a flag off EDNS0_EXPIRE and use that while keeping everything else the same. Perhaps Empty or ZeroLength or whatever.

@dmavrommatis
Copy link
Contributor Author

(Apologies for the absence on GitHub).

RFC 7314 says "This is done by adding a zero-length EDNS EXPIRE option to the options field of the OPT record when the query is made." so a zero length option is valid and something we should be handling. There's nothing in the RFC to say that the 32-bit value zero is reserved so we have to persist this somehow.

This PR isn't backward compatible though so we shouldn't merge as-is. What we could do is hang a flag off EDNS0_EXPIRE and use that while keeping everything else the same. Perhaps Empty or ZeroLength or whatever.

Can you elaborate for the backwards compatibility issue?
These functions are for packing and unpacking a message to bytes and the other way around. How will introducing a flag going to provide anything? In the end we will either write 0 bytes or 4 bytes.

@tmthrgd
Copy link
Collaborator

tmthrgd commented Oct 30, 2021

Any code that operates on EDNS0_EXPIRE would be broken by this as the type of Expire will have changed. Consider code that did something like (nonsense example):

func adjustExpire(opt *EDNS0_EXPIRE) {
	if opt.Expire < 10 {
		opt.Expire = 10
	} else {
		opt.Expire++
	}
}

Even code that simply inspects or prints the value of Expire will break.

A flag allows us to track whether we're writing zero or four bytes and persist that from unpack to pack without (hopefully) breaking any existing code.

@dmavrommatis
Copy link
Contributor Author

Any code that operates on EDNS0_EXPIRE would be broken by this as the type of Expire will have changed. Consider code that did something like (nonsense example):

func adjustExpire(opt *EDNS0_EXPIRE) {
	if opt.Expire < 10 {
		opt.Expire = 10
	} else {
		opt.Expire++
	}
}

Even code that simply inspects or prints the value of Expire will break.

A flag allows us to track whether we're writing zero or four bytes and persist that from unpack to pack without (hopefully) breaking any existing code.

oh gotcha, I will update the PR to avoid this issue

@dmavrommatis
Copy link
Contributor Author

@tmthrgd found some time to make the change. please check to see if the implementation is sufficient.

@dmavrommatis
Copy link
Contributor Author

hey @tmthrgd I think this PR is ready for merging!

edns.go Outdated Show resolved Hide resolved
@dmavrommatis
Copy link
Contributor Author

@tmthrgd @miekg can you check if the PR is complete now?

Copy link
Collaborator

@tmthrgd tmthrgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. As long as we're happy with the String output.

@miekg miekg merged commit d48e92a into miekg:master Mar 12, 2022
aanm pushed a commit to cilium/dns that referenced this pull request Jul 29, 2022
…ekg#1292) (miekg#1293)

* Change EDNS_EXPIRE field to support zero length option data (Resolves miekg#1292)

As per [RFC7134](https://datatracker.ietf.org/doc/html/rfc7314#section-2) the Expire
Option in queries should be zero-length. In the current implementation the field is
uint32 which always instatiates 4bytes for that field when packing to wire format.
For that reason we change the field to []uint8 so it can support 0-length and 4-byte
length option data.

* addressed comments

* addressed comments

* make change backwards compatible

* add comment for Empty field
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants