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
0744ca66
Commit
0744ca66
authored
Jan 25, 2014
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More DNSSEC caching logic, and avoid repeated validation of DS/DNSKEY
parent
2d33bda2
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
88 additions
and
84 deletions
+88
-84
src/dnsmasq.c
src/dnsmasq.c
+10
-2
src/dnssec.c
src/dnssec.c
+1
-1
src/forward.c
src/forward.c
+19
-27
src/rfc1035.c
src/rfc1035.c
+58
-54
No files found.
src/dnsmasq.c
View file @
0744ca66
...
...
@@ -141,10 +141,18 @@ int main (int argc, char **argv)
}
#endif
if
(
option_bool
(
OPT_DNSSEC_VALID
))
{
#ifdef HAVE_DNSSEC
if
(
daemon
->
cachesize
<
CACHESIZ
&&
option_bool
(
OPT_DNSSEC_VALID
))
die
(
_
(
"Cannot reduce cache size from default when DNSSEC enabled"
),
NULL
,
EC_BADCONF
);
if
(
!
daemon
->
dnskeys
)
die
(
_
(
"No trust anchors provided for DNSSEC"
),
NULL
,
EC_BADCONF
);
if
(
daemon
->
cachesize
<
CACHESIZ
)
die
(
_
(
"Cannot reduce cache size from default when DNSSEC enabled"
),
NULL
,
EC_BADCONF
);
#else
die
(
_
(
"DNSSEC not available: set HAVE_DNSSEC in src/config.h"
),
NULL
,
EC_BADCONF
);
#endif
}
#ifndef HAVE_TFTP
if
(
option_bool
(
OPT_TFTP
))
...
...
src/dnssec.c
View file @
0744ca66
...
...
@@ -1099,7 +1099,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
struct
all_addr
a
;
struct
blockdata
*
key
;
struct
crec
*
crecp
;
cache_start_insert
();
for
(
p2
=
ans_start
,
j
=
0
;
j
<
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
);
j
++
)
...
...
src/forward.c
View file @
0744ca66
...
...
@@ -855,42 +855,34 @@ void reply_query(int fd, int family, time_t now)
and validate them with the new data. Failure to find needed data here is an internal error.
Once we get to the original answer (FREC_DNSSEC_QUERY not set) and it validates,
return it to the original requestor. */
if
(
forward
->
flags
&
(
FREC_DNSKEY_QUERY
|
FREC_DS_QUERY
)
)
while
(
forward
->
dependent
)
{
while
(
forward
->
dependent
)
struct
frec
*
prev
=
forward
->
dependent
;
free_frec
(
forward
);
forward
=
prev
;
forward
->
blocking_query
=
NULL
;
/* already gone */
blockdata_retrieve
(
forward
->
stash
,
forward
->
stash_len
,
(
void
*
)
header
);
n
=
forward
->
stash_len
;
if
(
status
==
STAT_SECURE
)
{
struct
frec
*
prev
;
if
(
forward
->
flags
&
FREC_DNSKEY_QUERY
)
status
=
dnssec_validate_by_ds
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
forward
->
class
);
else
if
(
forward
->
flags
&
FREC_DS_QUERY
)
status
=
dnssec_validate_ds
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
forward
->
class
);
else
status
=
dnssec_validate_reply
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
&
forward
->
class
);
if
(
status
==
STAT_
SECURE
)
if
(
status
==
STAT_
NEED_DS
||
status
==
STAT_NEED_KEY
)
{
if
(
forward
->
flags
&
FREC_DNSKEY_QUERY
)
status
=
dnssec_validate_by_ds
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
forward
->
class
);
else
if
(
forward
->
flags
&
FREC_DS_QUERY
)
status
=
dnssec_validate_ds
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
forward
->
class
);
my_syslog
(
LOG_ERR
,
_
(
"Unexpected missing data for DNSSEC validation"
));
status
=
STAT_INSECURE
;
}
prev
=
forward
->
dependent
;
free_frec
(
forward
);
forward
=
prev
;
forward
->
blocking_query
=
NULL
;
/* already gone */
blockdata_retrieve
(
forward
->
stash
,
forward
->
stash_len
,
(
void
*
)
header
);
n
=
forward
->
stash_len
;
}
/* All DNSKEY and DS records done and in cache, now finally validate original
answer, provided last DNSKEY is OK. */
if
(
status
==
STAT_SECURE
)
status
=
dnssec_validate_reply
(
now
,
header
,
n
,
daemon
->
namebuff
,
daemon
->
keyname
,
&
forward
->
class
);
if
(
status
==
STAT_NEED_DS
||
status
==
STAT_NEED_KEY
)
{
my_syslog
(
LOG_ERR
,
_
(
"Unexpected missing data for DNSSEC validation"
));
status
=
STAT_INSECURE
;
}
}
if
(
status
==
STAT_TRUNCATED
)
header
->
hb3
|=
HB3_TC
;
header
->
hb3
|=
HB3_TC
;
else
log_query
(
F_KEYTAG
|
F_SECSTAT
,
"result"
,
NULL
,
status
==
STAT_SECURE
?
"SECURE"
:
(
status
==
STAT_INSECURE
?
"INSECURE"
:
"BOGUS"
));
...
...
src/rfc1035.c
View file @
0744ca66
...
...
@@ -1710,32 +1710,33 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
}
else
if
((
crecp
=
cache_find_by_addr
(
NULL
,
&
addr
,
now
,
is_arpa
)))
{
#ifdef HAVE_DNSSEC
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
|
F_CONFIG
))
&&
(
crecp
->
flags
&
F_DNSSECOK
)
&&
!
(
crecp
->
flags
&
F_NEG
)
&&
sec_reqd
&&
option_bool
(
OPT_DNSSEC_VALID
))
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
|
F_CONFIG
))
&&
sec_reqd
)
{
i
nt
gotsig
=
0
;
crecp
=
NULL
;
while
((
crecp
=
cache_find_by_name
(
crecp
,
name
,
now
,
F_DS
|
F_DNSKEY
))
)
i
f
(
!
option_bool
(
OPT_DNSSEC_VALID
)
||
((
crecp
->
flags
&
F_NEG
)
&&
(
crecp
->
flags
&
F_DNSSECOK
)))
crecp
=
NULL
;
#ifdef HAVE_DNSSEC
else
if
(
crecp
->
flags
&
F_DNSSECOK
)
{
if
(
crecp
->
addr
.
sig
.
type_covered
==
T_PTR
&&
crecp
->
uid
==
C_IN
)
int
gotsig
=
0
;
crecp
=
NULL
;
while
((
crecp
=
cache_find_by_name
(
crecp
,
name
,
now
,
F_DS
|
F_DNSKEY
)))
{
char
*
sigdata
=
blockdata_retrieve
(
crecp
->
addr
.
sig
.
keydata
,
crecp
->
addr
.
sig
.
keylen
,
NULL
);
gotsig
=
1
;
if
(
!
dryrun
&&
add_resource_record
(
header
,
limit
,
&
trunc
,
nameoffset
,
&
ansp
,
crecp
->
ttd
-
now
,
&
nameoffset
,
T_RRSIG
,
C_IN
,
"t"
,
crecp
->
addr
.
sig
.
keylen
,
sigdata
))
anscount
++
;
}
}
/* Need to re-run original cache search */
crecp
=
gotsig
?
cache_find_by_addr
(
NULL
,
&
addr
,
now
,
is_arpa
)
:
NULL
;
if
(
crecp
->
addr
.
sig
.
type_covered
==
T_PTR
&&
crecp
->
uid
==
C_IN
)
{
char
*
sigdata
=
blockdata_retrieve
(
crecp
->
addr
.
sig
.
keydata
,
crecp
->
addr
.
sig
.
keylen
,
NULL
);
gotsig
=
1
;
if
(
!
dryrun
&&
add_resource_record
(
header
,
limit
,
&
trunc
,
nameoffset
,
&
ansp
,
crecp
->
ttd
-
now
,
&
nameoffset
,
T_RRSIG
,
C_IN
,
"t"
,
crecp
->
addr
.
sig
.
keylen
,
sigdata
))
anscount
++
;
}
}
/* Need to re-run original cache search */
crecp
=
gotsig
?
cache_find_by_addr
(
NULL
,
&
addr
,
now
,
is_arpa
)
:
NULL
;
}
}
#endif
...
...
@@ -1918,42 +1919,45 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
crecp
=
save
;
}
#ifdef HAVE_DNSSEC
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
|
F_CONFIG
))
&&
(
crecp
->
flags
&
F_DNSSECOK
)
&&
!
(
crecp
->
flags
&
F_NEG
)
&&
sec_reqd
&&
option_bool
(
OPT_DNSSEC_VALID
))
/* If the client asked for DNSSEC and we can't provide RRSIGs, either
because we've not doing DNSSEC or the cached answer is signed by negative,
don't answer from the cache, forward instead. */
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
|
F_CONFIG
))
&&
sec_reqd
)
{
/* We're returning validated data, need to return the RRSIG too. */
int
sigtype
=
type
;
/* The signature may have expired even though the data is still in cache,
forward instead of answering from cache if so. */
int
gotsig
=
0
;
if
(
crecp
->
flags
&
F_CNAME
)
sigtype
=
T_CNAME
;
crecp
=
NULL
;
while
((
crecp
=
cache_find_by_name
(
crecp
,
name
,
now
,
F_DS
|
F_DNSKEY
)))
if
(
!
option_bool
(
OPT_DNSSEC_VALID
)
||
((
crecp
->
flags
&
F_NEG
)
&&
(
crecp
->
flags
&
F_DNSSECOK
)))
crecp
=
NULL
;
#ifdef HAVE_DNSSEC
else
if
(
crecp
->
flags
&
F_DNSSECOK
)
{
if
(
crecp
->
addr
.
sig
.
type_covered
==
sigtype
&&
crecp
->
uid
==
C_IN
)
/* We're returning validated data, need to return the RRSIG too. */
int
sigtype
=
type
;
/* The signature may have expired even though the data is still in cache,
forward instead of answering from cache if so. */
int
gotsig
=
0
;
if
(
crecp
->
flags
&
F_CNAME
)
sigtype
=
T_CNAME
;
crecp
=
NULL
;
while
((
crecp
=
cache_find_by_name
(
crecp
,
name
,
now
,
F_DS
|
F_DNSKEY
)))
{
char
*
sigdata
=
blockdata_retrieve
(
crecp
->
addr
.
sig
.
keydata
,
crecp
->
addr
.
sig
.
keylen
,
NULL
);
gotsig
=
1
;
if
(
!
dryrun
&&
add_resource_record
(
header
,
limit
,
&
trunc
,
nameoffset
,
&
ansp
,
crecp
->
ttd
-
now
,
&
nameoffset
,
T_RRSIG
,
C_IN
,
"t"
,
crecp
->
addr
.
sig
.
keylen
,
sigdata
))
anscount
++
;
if
(
crecp
->
addr
.
sig
.
type_covered
==
sigtype
&&
crecp
->
uid
==
C_IN
)
{
char
*
sigdata
=
blockdata_retrieve
(
crecp
->
addr
.
sig
.
keydata
,
crecp
->
addr
.
sig
.
keylen
,
NULL
);
gotsig
=
1
;
if
(
!
dryrun
&&
add_resource_record
(
header
,
limit
,
&
trunc
,
nameoffset
,
&
ansp
,
crecp
->
ttd
-
now
,
&
nameoffset
,
T_RRSIG
,
C_IN
,
"t"
,
crecp
->
addr
.
sig
.
keylen
,
sigdata
))
anscount
++
;
}
}
/* Need to re-run original cache search */
crecp
=
gotsig
?
cache_find_by_name
(
NULL
,
name
,
now
,
flag
|
F_CNAME
)
:
NULL
;
}
/* Need to re-run original cache search */
crecp
=
gotsig
?
cache_find_by_name
(
NULL
,
name
,
now
,
flag
|
F_CNAME
)
:
NULL
;
}
}
#endif
if
(
crecp
)
do
...
...
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