BIND 10 #1104: support TSIG in DNS (Request) ACL
BIND 10 Development
do-not-reply at isc.org
Tue Aug 2 01:24:01 UTC 2011
#1104: support TSIG in DNS (Request) ACL
-------------------------------------+-------------------------------------
Reporter: | Owner: jinmei
jinmei | Status: reviewing
Type: task | Milestone:
Priority: major | Sprint-20110802
Component: | Resolution:
xfrout | Sensitive: 0
Keywords: | Sub-Project: DNS
Defect Severity: N/A | Estimated Difficulty: 5
Feature Depending on Ticket: | Total Hours: 0
Add Hours to Ticket: 0 |
Internal?: 0 |
-------------------------------------+-------------------------------------
Comment (by jinmei):
Replying to [comment:12 stephen]:
> > ...one possible solution is to enhance the TSIGRecord class so that it
can store a state indicating the record has been verified, and have
TSIGContext::verify() change the state to "verified" on success (to make
it possible we need to stop constifying the 'record' parameter,
> though).
> As part of a solution to avoid avoid multiple verifications of the same
record, that would work. To avoid the overhead involved with
"unconstifying" TSIGContext, we could make the internal "verified" flag
mutable.
Firs off: in case I was not clear, what I suggested is to introduce a
"verified" flag to the TSIGRecord class, not TSIGContext. And as a
result we'll have to change from:
{{{
TSIGError
TSIGContext::verify(const TSIGRecord* const record, const void* const
data,
const size_t data_len)
}}}
to:
{{{
TSIGError
TSIGContext::verify(TSIGRecord* const record, const void* const data,
const size_t data_len)
}}}
(where the "verified" flag of 'record' may be modified).
I don't think it a good idea to deceive the compiler with mutable in
this case. When we set the "verified" flag of TSIGRecord, it actually
changes externally observable behavior. IMO hiding the fact with
mutable goes beyond the acceptable usage of it.
Another approach would be to pass TSIGContext instead of TSIGRecord to
RequestContext. TSIGContext (internally) contains information of the
result of the latest verification and the associated TSIG key, so we
could expose these to RequestContext as read only attributes. One
possible drawback is that this approach would be a bit more error
prone than the approach of passing TSIGRecord. For example, an
extremely buggy implementation may reuse a TSIGContext that has
validated a signature multiple times for different ACL checks. Such a
bug can happen with TSIGRecord, too, but it will be less likely if the
expected usage is to pass the result of Message::getTSIGRecord() to
the RequestContext constructor (then the application never holds a
reference to the TSIG record itself).
> > Then we can change !RequestContext so that it will ignore the given
TSIG record unless its state is "verified".
> I'm not sure what you meant here. If an ACL requires a check on a TSIG
record, that check needs to be carried out; you can't ignore the record
just because it has not been verified.
For the purpose of ACL we only use the TSIG key name (at least in the
current implementation, and as in BIND 9 and NSD). So the proposed
logic would be to change this:
{{{
template<>
bool
NameCheck<RequestContext>::matches(const RequestContext& request) const {
return (request.tsig != NULL && request.tsig->getName() == name_);
}
}}}
to this:
{{{
template<>
bool
NameCheck<RequestContext>::matches(const RequestContext& request) const {
return (request.tsig != NULL && request.tsig->isVerified() &&
request.tsig->getName() == name_);
}
}}}
> Using your idea, I was more envisaging TSIGContext::verify() being
called during the ACL checking procedure (and in other places), performing
the verification if called for the first time and returning the stored
verification state on subsequent calls.
I was aware of that possibility, but didn't think it the best away to
handle this issue. IMO, if an application wants to handle TSIG, it
should explicitly do it at an appropriate position of the code. On
one hand it may look convenient if we merge TSIG verification in ACL
checks (in addition to doing verification separately), but it will
make the ACL module have tighter coupling with DNS specific logic,
which will subsequently lead to reducing clarity. It would also
require that RequestContext be modifiable in matches(), which is
against an assumption of the method. Further, deeper inspection
before performing TSIG verification could be even dangerous, because
some of the checks may depend on the integrity of the message content
(e.g., whether a particular header flag is on/off) but we cannot rely
on the integrity until we perform the signature.
I still tend to agree on providing a safety net for naive/buggy
implementations that don't correctly perform TSIG check but still
do pass a TSIG record to RequestContext (with which, as you pointed
out, an ACL with TSIG key would cause a confusing/insecure result).
But I believe it should be a minimal guard that is sufficient to
prevent the harmful result, and shouldn't try to be too smart.
Now, as this point seems to be not so trivial, my current suggestion
is to create a new ticket as an open enhancement, referring to this
discussion, and close this one. Would that be okay for you? (If you
like it I don't mind with keeping this ticket open instead of creating
a new one).
--
Ticket URL: <http://bind10.isc.org/ticket/1104#comment:14>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list