Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
D
Dnsmasq
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Dnsmasq
Commits
e3ec6f0b
Commit
e3ec6f0b
authored
Jun 12, 2015
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Handle CNAMEs to DS records when confirming absence of DS for DNSSEC.
parent
f7bfbdc8
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
68 additions
and
10 deletions
+68
-10
src/dnssec.c
src/dnssec.c
+34
-6
src/forward.c
src/forward.c
+34
-4
No files found.
src/dnssec.c
View file @
e3ec6f0b
...
@@ -1223,8 +1223,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
...
@@ -1223,8 +1223,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
val
=
dnssec_validate_reply
(
now
,
header
,
plen
,
name
,
keyname
,
NULL
,
&
neganswer
,
&
nons
);
val
=
dnssec_validate_reply
(
now
,
header
,
plen
,
name
,
keyname
,
NULL
,
&
neganswer
,
&
nons
);
/* Note dnssec_validate_reply() will have cached positive answers */
/* Note dnssec_validate_reply() will have cached positive answers */
if
(
val
==
STAT_
NO_SIG
||
val
==
STAT_
INSECURE
)
if
(
val
==
STAT_INSECURE
)
val
=
STAT_BOGUS
;
val
=
STAT_BOGUS
;
if
(
val
==
STAT_NO_SIG
)
return
val
;
p
=
(
unsigned
char
*
)(
header
+
1
);
p
=
(
unsigned
char
*
)(
header
+
1
);
extract_name
(
header
,
plen
,
&
p
,
name
,
1
,
4
);
extract_name
(
header
,
plen
,
&
p
,
name
,
1
,
4
);
...
@@ -1875,11 +1878,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
...
@@ -1875,11 +1878,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if
(
neganswer
&&
!
have_answer
)
if
(
neganswer
&&
!
have_answer
)
*
neganswer
=
1
;
*
neganswer
=
1
;
/* No data, therefore no sigs */
/* No data, therefore no sigs */
if
(
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
==
0
)
if
(
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
==
0
)
return
STAT_NO_SIG
;
{
*
keyname
=
0
;
return
STAT_NO_SIG
;
}
for
(
p1
=
ans_start
,
i
=
0
;
i
<
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
);
i
++
)
for
(
p1
=
ans_start
,
i
=
0
;
i
<
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
);
i
++
)
{
{
if
(
!
extract_name
(
header
,
plen
,
&
p1
,
name
,
1
,
10
))
if
(
!
extract_name
(
header
,
plen
,
&
p1
,
name
,
1
,
10
))
...
@@ -1948,6 +1954,19 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
...
@@ -1948,6 +1954,19 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
{
{
if
(
class
)
if
(
class
)
*
class
=
class1
;
/* Class for DS or DNSKEY */
*
class
=
class1
;
/* Class for DS or DNSKEY */
if
(
rc
==
STAT_NO_SIG
)
{
/* If we dropped off the end of a CNAME chain, return
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
if DS records in CNAME chains. */
if
(
cname_count
==
CNAME_CHAIN
||
i
<
ntohs
(
header
->
ancount
))
/* No CNAME chain, or no sig in answer section, return empty name. */
*
keyname
=
0
;
else
if
(
!
extract_name
(
header
,
plen
,
&
qname
,
keyname
,
1
,
0
))
return
STAT_BOGUS
;
}
return
rc
;
return
rc
;
}
}
...
@@ -2060,8 +2079,17 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
...
@@ -2060,8 +2079,17 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
/* First marshall the NSEC records, if we've not done it previously */
/* First marshall the NSEC records, if we've not done it previously */
if
(
!
nsec_type
&&
!
(
nsec_type
=
find_nsec_records
(
header
,
plen
,
&
nsecs
,
&
nsec_count
,
qclass
)))
if
(
!
nsec_type
&&
!
(
nsec_type
=
find_nsec_records
(
header
,
plen
,
&
nsecs
,
&
nsec_count
,
qclass
)))
return
STAT_NO_SIG
;
/* No NSECs, this is probably a dangling CNAME pointing into
{
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
/* No NSEC records. If we dropped off the end of a CNAME chain, return
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
if DS records in CNAME chains. */
if
(
cname_count
==
CNAME_CHAIN
)
/* No CNAME chain, return empty name. */
*
keyname
=
0
;
else
if
(
!
extract_name
(
header
,
plen
,
&
qname
,
keyname
,
1
,
0
))
return
STAT_BOGUS
;
return
STAT_NO_SIG
;
/* No NSECs, this is probably a dangling CNAME pointing into
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
}
/* Get name of missing answer */
/* Get name of missing answer */
if
(
!
extract_name
(
header
,
plen
,
&
qname
,
name
,
1
,
0
))
if
(
!
extract_name
(
header
,
plen
,
&
qname
,
name
,
1
,
0
))
...
...
src/forward.c
View file @
e3ec6f0b
...
@@ -851,7 +851,7 @@ void reply_query(int fd, int family, time_t now)
...
@@ -851,7 +851,7 @@ void reply_query(int fd, int family, time_t now)
Avoid caching a reply with sigs if there's a vaildated break in the
Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */
DS chain, so we don't return replies from cache missing sigs. */
status
=
STAT_INSECURE_DS
;
status
=
STAT_INSECURE_DS
;
else
if
(
status
==
STAT_NO_NS
)
else
if
(
status
==
STAT_NO_NS
||
status
==
STAT_NO_SIG
)
status
=
STAT_BOGUS
;
status
=
STAT_BOGUS
;
}
}
else
if
(
forward
->
flags
&
FREC_CHECK_NOSIGN
)
else
if
(
forward
->
flags
&
FREC_CHECK_NOSIGN
)
...
@@ -997,7 +997,7 @@ void reply_query(int fd, int family, time_t now)
...
@@ -997,7 +997,7 @@ void reply_query(int fd, int family, time_t now)
Avoid caching a reply with sigs if there's a vaildated break in the
Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */
DS chain, so we don't return replies from cache missing sigs. */
status
=
STAT_INSECURE_DS
;
status
=
STAT_INSECURE_DS
;
else
if
(
status
==
STAT_NO_NS
)
else
if
(
status
==
STAT_NO_NS
||
status
==
STAT_NO_SIG
)
status
=
STAT_BOGUS
;
status
=
STAT_BOGUS
;
}
}
else
if
(
forward
->
flags
&
FREC_CHECK_NOSIGN
)
else
if
(
forward
->
flags
&
FREC_CHECK_NOSIGN
)
...
@@ -1456,6 +1456,21 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
...
@@ -1456,6 +1456,21 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
if
(
status
==
STAT_BOGUS
)
if
(
status
==
STAT_BOGUS
)
return
STAT_BOGUS
;
return
STAT_BOGUS
;
if
(
status
==
STAT_NO_SIG
&&
*
keyname
!=
0
)
{
/* There is a validated CNAME chain that doesn't end in a DS record. Start
the search again in that domain. */
blockdata_free
(
forward
->
orig_domain
);
forward
->
name_start
=
strlen
(
keyname
);
forward
->
name_len
=
forward
->
name_start
+
1
;
if
(
!
(
forward
->
orig_domain
=
blockdata_alloc
(
keyname
,
forward
->
name_len
)))
return
STAT_BOGUS
;
strcpy
(
name
,
keyname
);
status
=
0
;
/* force to cache when we iterate. */
continue
;
}
/* There's a proven DS record, or we're within a zone, where there doesn't need
/* There's a proven DS record, or we're within a zone, where there doesn't need
to be a DS record. Add a name and try again.
to be a DS record. Add a name and try again.
If we've already tried the whole name, then fail */
If we've already tried the whole name, then fail */
...
@@ -1572,6 +1587,21 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
...
@@ -1572,6 +1587,21 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
return
STAT_INSECURE
;
return
STAT_INSECURE
;
}
}
if
(
status
==
STAT_NO_SIG
&&
*
keyname
!=
0
)
{
/* There is a validated CNAME chain that doesn't end in a DS record. Start
the search again in that domain. */
blockdata_free
(
block
);
name_len
=
strlen
(
keyname
)
+
1
;
name_start
=
name
+
name_len
-
1
;
if
(
!
(
block
=
blockdata_alloc
(
keyname
,
name_len
)))
return
STAT_BOGUS
;
strcpy
(
name
,
keyname
);
continue
;
}
if
(
status
==
STAT_BOGUS
)
if
(
status
==
STAT_BOGUS
)
{
{
free
(
packet
);
free
(
packet
);
...
@@ -1627,7 +1657,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
...
@@ -1627,7 +1657,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{
{
if
(
new_status
==
STAT_NO_DS
)
if
(
new_status
==
STAT_NO_DS
)
new_status
=
STAT_INSECURE_DS
;
new_status
=
STAT_INSECURE_DS
;
else
if
(
new_status
==
STAT_NO_NS
)
else
if
(
new_status
==
STAT_NO_NS
||
new_status
==
STAT_NO_SIG
)
new_status
=
STAT_BOGUS
;
new_status
=
STAT_BOGUS
;
}
}
}
}
...
@@ -1692,7 +1722,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
...
@@ -1692,7 +1722,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{
{
if
(
new_status
==
STAT_NO_DS
)
if
(
new_status
==
STAT_NO_DS
)
new_status
=
STAT_INSECURE_DS
;
new_status
=
STAT_INSECURE_DS
;
else
if
(
new_status
==
STAT_NO_NS
)
else
if
(
new_status
==
STAT_NO_NS
||
new_status
==
STAT_NO_SIG
)
new_status
=
STAT_BOGUS
;
/* Validated no DS */
new_status
=
STAT_BOGUS
;
/* Validated no DS */
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment