BIND 10 #506: Analysis of Wildcard Processing
BIND 10 Development
do-not-reply at isc.org
Fri Jan 28 08:35:19 UTC 2011
#506: Analysis of Wildcard Processing
-------------------------------------+-------------------------------------
Reporter: stephen | Owner: jinmei
Type: | Status: accepted
enhancement | Milestone: A-Team-
Priority: major | Sprint-20110209
Component: | Resolution:
b10-auth | Sensitive: 0
Keywords: | Add Hours to Ticket: 0
Estimated Number of Hours: 3.0 | Total Hours: 0
Billable?: 1 |
Internal?: 0 |
-------------------------------------+-------------------------------------
Comment (by jinmei):
This is a more complete version of BIND 9's wildcard handling
in its rbtdb. I've simplified the logic a bit for (the current
implementation of) the BIND 10 in-memory zone.
'''Loading'''
The basic idea is to mark the parent node of a wildcard name
(e.g. example.com for *.example.com) in order to force the find()
logic to perform special callback (like delegation).
This proces is two-fold:
- when loading an RRset, if the owner name is a wildcard (e.g.
*.foo.example.com) and the RR type is !NS && !NSEC3, enable callback
for
the parent node (e.g. foo.example.com), and mark that node as "wild".
- for any owner name, check if any of its ancestor is a wildcard.
this is the case, e.g., when adding "foo.*.example.com", which would
result in an empty non terminal wildcard node for name "*.example.com".
Note: adding such a name as "foo.*.example.com" is almost bogus, and
BIND 9 rejects loading them by default. It's still not prohibited
by the protocol spec, however. If an ancestor name is a wildcard,
explicitly add a rbt node for that name (to make sure if can find it
as an exact match by find()), and mark its parent as "wild".
'''Finding (wildcard matching)'''
First, add a new member variable "wild" (boolean) to FindState.
If true, it means find() encounters a "wild" node during the search.
We also need a new primitive to get the "previous" node of a given
RBTree node (for a minor case handling).
- in zonecutCallback(), if it's not a delegation and the node is marked
as "wild", set FindState::wild to true. on the other hand, once it
encounters a delegation, reset it to false. RFC1034 requires we cancel
wildcard matching on delegation (Section 4.3.3)
- in find(), if the search result is PARTIALMATCH and it's not a
delegation,
perform the wildcard check. It works as follows:
1. if the search stops at a node marked as "wild", that may be a
wildcard match. otherwise, it's not (this case is possible if
there are *.example.com and foo.example.com, and the query name
is bar.foo.example.com).
2. if it can be a wildcard match, construct the wildcard name by
prepending '*' to the node's abstract name.
3. get the RBTree node for that wildcard name by searching RBTree.
4. reject the case where the query name is a subdomain of an empty
non terminal node under the node marked as "wild" (which was found
in the first find()). This process is complicated, so it's described
separately below.
5. if the wildcard match is allowed, use the RRsets for the wildcard
node, and return any positive response with replacing the owner name
of the RRset (which is the wildcard name) with the query name.
'''Cancel wildcard match due to an empty non terminal'''
This process is details of step 4 of the wildcard check in the previous
section. It implements the following part of Section 4.3.3 of RFC1034:
{{{
- When the query name or a name between the wildcard domain and
the query name is know to exist.
}}}
Specifically, when the wildcard name *.example.com and the zone has
bar.foo.example.com, this process will reject aaa.foo.example.com
and zzz.foo.example.com to be matched against the wildcard.
The necessary steps are as follows:
- get the previous and next node (in DNSSEC order) of the last matching
node for aaa.foo.example.com, they are *.example.com and
bar.foo.example.com, respectively; for zzz.foo.example.com, they are
aaa.foo.example.com and something else (or none), respectively.
- check if any ancestor name of the query name (including the qname
itself) up to the node marked as "wild" (in this case example.com)
is a super domain of either the previous and next node name.
For aaa.foo.example.com, its 1-generation ancestor, foo.example.com
is a super domain of the next, "bar.foo.example.com"; for
zzz.example.com,
its 1-generation ancestor, again foo.example.com is a super domain
of the previous, "bar.foo.example.com". This means the query name
is a subdomain of an empty non terminal under the "wild" node,
foo.example.com, and should not allow wildcard match.
'''proposed subtasks'''
I propose breaking down the above into the following 4 sub tasks:
- loading part
- finding part (except the non empty terminal rejection)
- a new primitive for rbtree to get the previous node of a given node
(this task can be done separately)
- implement canceling wildcard match due to an empty non terminal.
it requires the new primitive described in the previous bullet.
--
Ticket URL: <http://bind10.isc.org/ticket/506#comment:3>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list