* Allow use of fs.FS for $INCLUDE and wrap errors
This adds ZoneParser.SetIncludeAllowedFS, to specify an fs.FS when
enabling support for $INCLUDE, for reading included files from
somewhere other than the local filesystem.
I've also modified ParseError to support wrapping another error, such
as errors encountered while opening the $INCLUDE target. This allows
for much more robust handling, using errors.Is() instead of testing
for particular strings (which may not be identical between fs.FS
implementations).
ParseError was being constructed in a lot of places using positional
instead of named members. Updating ParseError initialization after
the new member field was added makes this change seem a lot larger
than it actually is.
The changes here should be completely backwards compatible. The
ParseError change should be invisible to anyone not trying to unwrap
it, and ZoneParser will continue to use os.Open if the existing
SetIncludeAllowed method is called instead of the new
SetIncludeAllowedFS method.
* Don't duplicate SetIncludeAllowed; clarify edge cases
Rather than duplicate functionality between SetIncludeAllowed and
SetIncludeAllowedFS, have a method SetIncludeFS, which only sets the
fs.FS.
I've improved the documentation to point out some considerations for
users hoping to use fs.FS as a security boundary.
Per the fs.ValidPath documentation, fs.FS implementations must use
path (not filepath) semantics, with slash as a separator (even on
Windows). Some, like os.DirFS, also require all paths to be relative.
I've clarified this in the documentation, made the includePath
manipulation more robust to edge cases, and added some additional
tests for relative and absolute paths.
We definitely shouldn't be using goto for a simple loop.
This is technically a behaviour change when off == len(msg), but we're
always called with off < len(msg) so this is unobservable.
* Avoid using strings.Split
strings.Split has to allocate for the return slice. This allocation
was wasteful in ever case it was used in this library.
Instead we use the new strings.Cut and other string manipulation where
appropriate. This tends to lead to cleaner and more readable code in
addition to the benefits this has on the garbage collector.
* Further simplify structTag in the msg_generate.go
This doesn't need to call strings.TrimPrefix twice.
This function was previously changed from using strings.ToLower to a
custom loop to ensure it only lowercases ASCII characters. This was
more complicated than it needed to be and introduced more allocations
than is necessary.
Instead of that approach we call strings.Map with a simple ASCII
lowercase mapping function. Sadly we still use the nice ASCII-only fast
path that strings.ToLower had, but it's unlikely to be worth all the
extra code.
According to Section 6.2 [1] of RFC 4034,all uppercase US-ASCII letters in the
owner name of the RR are replaced by the corresponding lowercase US-ASCII
letters.
This updates CanonicalName to conform to the RFC.
[1] https://www.rfc-editor.org/rfc/rfc4034#section-6.2Fixesmiekg/dns#1434
In order to parse an IPv4 address encoded as IPv6 it needs to have the
prefix of "::ffff:" i.e. ::ffff:192.0.2.1
Co-authored-by: Christian Elmerot <elmerot@cloudflare.com>
If we want to use a custom mechanism of obtaining a Conn that doesn't
match the net.Dialer type, but retain the timeout behaviour from
ExchangeContext, there was previously no way to accomplish this.
This PR makes the underlying ExchangeWithConnContext function public,
which allows this behaviour.
Now that #1454 is merged, there is no longer any interaction between the
context provided and the singleflight behaviour, so I removed the
comment from ExchangeWithConn.
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
* Allow RRSIG algorithm mnemonics
Java outputs these *and* the RFC says we should parse them, so parse
them. We'll never output them though. Throwback to the "be lenient to
what you accept, but strict with what you output". Anyhow the diff is
tiny and it helps interop.
Fixes: #1447
Signed-off-by: Miek Gieben <miek@miek.nl>
* Check parsed algorithm
Signed-off-by: Miek Gieben <miek@miek.nl>
---------
Signed-off-by: Miek Gieben <miek@miek.nl>
* In func (zl *zlexer) Next() (lex, bool)
make max token size buffers str and com something we can grow.
Why? Because.
Reasons: When experimenting with OPENPGPKEY records, which themselves
are basically a key, if my zone file already has an RSA 4096 public key
record, this lib goes boom:
dns: bad OPENPGPKEY PublicKey: "token length insufficient for parsing" at line: .....
The key is good.
Testing against bare ed25519 keys whose base64 length is ~320 characters
and there are no problems
Testing against a bare RSA4096 key whose base64 length is ~3100 characters
and: problems.
Bare is the key word here, since for DNS, one ideally publishes as bare
a key as possible, minus signatures, minus photos, minus extra
metadata beyond the essential that will push a record length up.
A typical public key with two RSA 4K subkeys and several signatures may
rise to > ~21000 bytes.
* Test case for OPENPGPKEY (valid, test pgp public keys)
Reverse TLSA test record fail logic
TestNewRRCommentLengthCrasherString: ...
* Improve IsFQDN performance
While this code may be slightly less clear, it's significantly faster
and this function seems to be a hot path for certain workloads.
name old time/op new time/op delta
IsFQDN/no_dot-12 5.86ns ± 2% 1.48ns ± 3% -74.71% (p=0.000 n=10+10)
IsFQDN/unescaped-12 8.73ns ± 2% 1.57ns ± 1% -81.98% (p=0.000 n=9+8)
IsFQDN/escaped-12 27.4ns ± 2% 23.8ns ± 2% -13.19% (p=0.000 n=10+10)
FQDN/is_fqdn-12 8.36ns ± 1% 1.80ns ± 2% -78.50% (p=0.000 n=9+10)
FQDN/not_fqdn-12 36.8ns ±15% 33.4ns ±12% -9.25% (p=0.035 n=10+10)
* Fixup IsFQDN comment
* Use generics for dddToByte and dddStringToByte
* Introduce generic isDDD helper
Almost all uses of isDigit look exactly the same, turn them into a
matching helper.
* Introduce a generic slice clone function
This is nil-preserving unlike the existing code.
We also add some missing []byte slice copies.
* Move cloneSlice call into &RR{...} in types_generate.go
* Wrap longer copy lines in types_generate.go
* fix typo
* more IPSECKEY/AMTRELAY tests
* avoid bytes.Equal for IP comparison
* *_generate: convert fprintf with no argument to fprint, add newlines to ztypes so gofumpt doesn't try to fix it