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
a25720a3
Commit
a25720a3
authored
Jan 14, 2014
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
protocol handling for DNSSEC
parent
cc111e0b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
64 additions
and
24 deletions
+64
-24
src/dnsmasq.h
src/dnsmasq.h
+2
-1
src/forward.c
src/forward.c
+26
-2
src/option.c
src/option.c
+3
-3
src/rfc1035.c
src/rfc1035.c
+33
-18
No files found.
src/dnsmasq.h
View file @
a25720a3
...
@@ -230,7 +230,8 @@ struct event_desc {
...
@@ -230,7 +230,8 @@ struct event_desc {
#define OPT_QUIET_DHCP6 43
#define OPT_QUIET_DHCP6 43
#define OPT_QUIET_RA 44
#define OPT_QUIET_RA 44
#define OPT_DNSSEC_VALID 45
#define OPT_DNSSEC_VALID 45
#define OPT_LAST 46
#define OPT_DNSSEC_PERMISS 46
#define OPT_LAST 47
/* extra flags for my_syslog, we use a couple of facilities since they are known
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
...
...
src/forward.c
View file @
a25720a3
...
@@ -511,7 +511,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
...
@@ -511,7 +511,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if
(
option_bool
(
OPT_DNSSEC_VALID
))
if
(
option_bool
(
OPT_DNSSEC_VALID
))
header
->
hb4
&=
~
HB4_AD
;
header
->
hb4
&=
~
HB4_AD
;
if
(
cache_secure
)
if
(
!
(
header
->
hb4
&
HB4_CD
)
&&
cache_secure
)
header
->
hb4
|=
HB4_AD
;
header
->
hb4
|=
HB4_AD
;
#endif
#endif
...
@@ -556,6 +556,31 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
...
@@ -556,6 +556,31 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
}
}
}
}
#ifdef HAVE_DNSSEC
if
(
no_cache
&&
!
(
header
->
hb4
&
HB4_CD
))
{
if
(
option_bool
(
OPT_DNSSEC_PERMISS
))
{
unsigned
short
type
;
char
types
[
20
];
if
(
extract_request
(
header
,
(
size_t
)
n
,
daemon
->
namebuff
,
&
type
))
{
querystr
(
""
,
types
,
type
);
my_syslog
(
LOG_WARNING
,
_
(
"DNSSEC validation failed: query %s%s"
),
daemon
->
namebuff
,
types
);
}
else
my_syslog
(
LOG_WARNING
,
_
(
"DNSSEC validation failed for unknown query"
));
}
else
{
/* Bogus reply, turn into SERVFAIL */
SET_RCODE
(
header
,
SERVFAIL
);
munged
=
1
;
}
}
#endif
/* do this after extract_addresses. Ensure NODATA reply and remove
/* do this after extract_addresses. Ensure NODATA reply and remove
nameserver info. */
nameserver info. */
...
@@ -824,7 +849,6 @@ void reply_query(int fd, int family, time_t now)
...
@@ -824,7 +849,6 @@ void reply_query(int fd, int family, time_t now)
if
(
status
==
STAT_SECURE
)
if
(
status
==
STAT_SECURE
)
cache_secure
=
1
;
cache_secure
=
1
;
/* TODO return SERVFAIL here */
else
if
(
status
==
STAT_BOGUS
)
else
if
(
status
==
STAT_BOGUS
)
no_cache_dnssec
=
1
;
no_cache_dnssec
=
1
;
...
...
src/option.c
View file @
a25720a3
...
@@ -140,7 +140,7 @@ struct myoption {
...
@@ -140,7 +140,7 @@ struct myoption {
#define LOPT_QUIET_RA 328
#define LOPT_QUIET_RA 328
#define LOPT_SEC_VALID 329
#define LOPT_SEC_VALID 329
#define LOPT_DNSKEY 330
#define LOPT_DNSKEY 330
#define LOPT_DNSSEC_PERM 331
#ifdef HAVE_GETOPT_LONG
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
static
const
struct
option
opts
[]
=
...
@@ -278,6 +278,7 @@ static const struct myoption opts[] =
...
@@ -278,6 +278,7 @@ static const struct myoption opts[] =
{
"synth-domain"
,
1
,
0
,
LOPT_SYNTH
},
{
"synth-domain"
,
1
,
0
,
LOPT_SYNTH
},
{
"dnssec"
,
0
,
0
,
LOPT_SEC_VALID
},
{
"dnssec"
,
0
,
0
,
LOPT_SEC_VALID
},
{
"dnskey"
,
1
,
0
,
LOPT_DNSKEY
},
{
"dnskey"
,
1
,
0
,
LOPT_DNSKEY
},
{
"dnssec-permissive"
,
0
,
0
,
LOPT_DNSSEC_PERM
},
#ifdef OPTION6_PREFIX_CLASS
#ifdef OPTION6_PREFIX_CLASS
{
"dhcp-prefix-class"
,
1
,
0
,
LOPT_PREF_CLSS
},
{
"dhcp-prefix-class"
,
1
,
0
,
LOPT_PREF_CLSS
},
#endif
#endif
...
@@ -428,10 +429,9 @@ static struct {
...
@@ -428,10 +429,9 @@ static struct {
{
LOPT_AUTHPEER
,
ARG_DUP
,
"<ipaddr>[,<ipaddr>...]"
,
gettext_noop
(
"Peers which are allowed to do zone transfer"
),
NULL
},
{
LOPT_AUTHPEER
,
ARG_DUP
,
"<ipaddr>[,<ipaddr>...]"
,
gettext_noop
(
"Peers which are allowed to do zone transfer"
),
NULL
},
{
LOPT_IPSET
,
ARG_DUP
,
"/<domain>/<ipset>[,<ipset>...]"
,
gettext_noop
(
"Specify ipsets to which matching domains should be added"
),
NULL
},
{
LOPT_IPSET
,
ARG_DUP
,
"/<domain>/<ipset>[,<ipset>...]"
,
gettext_noop
(
"Specify ipsets to which matching domains should be added"
),
NULL
},
{
LOPT_SYNTH
,
ARG_DUP
,
"<domain>,<range>,[<prefix>]"
,
gettext_noop
(
"Specify a domain and address range for synthesised names"
),
NULL
},
{
LOPT_SYNTH
,
ARG_DUP
,
"<domain>,<range>,[<prefix>]"
,
gettext_noop
(
"Specify a domain and address range for synthesised names"
),
NULL
},
#ifdef HAVE_DNSSEC
{
LOPT_SEC_VALID
,
OPT_DNSSEC_VALID
,
NULL
,
gettext_noop
(
"Activate DNSSEC validation"
),
NULL
},
{
LOPT_SEC_VALID
,
OPT_DNSSEC_VALID
,
NULL
,
gettext_noop
(
"Activate DNSSEC validation"
),
NULL
},
{
LOPT_DNSKEY
,
ARG_DUP
,
"<domain>,<algo>,<key>"
,
gettext_noop
(
"Specify trust anchor DNSKEY"
),
NULL
},
{
LOPT_DNSKEY
,
ARG_DUP
,
"<domain>,<algo>,<key>"
,
gettext_noop
(
"Specify trust anchor DNSKEY"
),
NULL
},
#endif
{
LOPT_DNSSEC_PERM
,
OPT_DNSSEC_PERMISS
,
NULL
,
gettext_noop
(
"Do NOT return SERVFAIL whne DNSSEC validation fails."
),
NULL
},
#ifdef OPTION6_PREFIX_CLASS
#ifdef OPTION6_PREFIX_CLASS
{
LOPT_PREF_CLSS
,
ARG_DUP
,
"set:tag,<class>"
,
gettext_noop
(
"Specify DHCPv6 prefix class"
),
NULL
},
{
LOPT_PREF_CLSS
,
ARG_DUP
,
"set:tag,<class>"
,
gettext_noop
(
"Specify DHCPv6 prefix class"
),
NULL
},
#endif
#endif
...
...
src/rfc1035.c
View file @
a25720a3
...
@@ -511,14 +511,17 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
...
@@ -511,14 +511,17 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
)
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
)
{
{
unsigned
char
*
lenp
,
*
datap
,
*
p
;
unsigned
char
*
lenp
,
*
datap
,
*
p
;
int
rdlen
;
int
rdlen
,
is_sign
;
if
(
ntohs
(
header
->
arcount
)
==
0
)
if
(
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
))
)
{
{
if
(
is_sign
)
return
plen
;
/* We are adding the pseudoheader */
/* We are adding the pseudoheader */
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
!
(
p
=
skip_section
(
p
,
!
(
p
=
skip_section
(
p
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
+
ntohs
(
header
->
arcount
)
,
header
,
plen
)))
header
,
plen
)))
return
plen
;
return
plen
;
*
p
++
=
0
;
/* empty name */
*
p
++
=
0
;
/* empty name */
...
@@ -531,16 +534,16 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
...
@@ -531,16 +534,16 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
rdlen
=
0
;
rdlen
=
0
;
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
return
plen
;
/* Too big */
header
->
arcount
=
htons
(
1
);
header
->
arcount
=
htons
(
ntohs
(
header
->
arcount
)
+
1
);
datap
=
p
;
datap
=
p
;
}
}
else
else
{
{
int
i
,
is_sign
;
int
i
;
unsigned
short
code
,
len
,
flags
;
unsigned
short
code
,
len
,
flags
;
/* Must be at the end, if exists */
if
(
ntohs
(
header
->
arcount
)
!=
1
||
if
(
ntohs
(
header
->
arcount
)
!=
1
||
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
))
||
is_sign
||
is_sign
||
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
plen
;
return
plen
;
...
@@ -1147,7 +1150,6 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
...
@@ -1147,7 +1150,6 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
/* If the packet holds exactly one query
/* If the packet holds exactly one query
return F_IPV4 or F_IPV6 and leave the name from the query in name */
return F_IPV4 or F_IPV6 and leave the name from the query in name */
unsigned
int
extract_request
(
struct
dns_header
*
header
,
size_t
qlen
,
char
*
name
,
unsigned
short
*
typep
)
unsigned
int
extract_request
(
struct
dns_header
*
header
,
size_t
qlen
,
char
*
name
,
unsigned
short
*
typep
)
{
{
unsigned
char
*
p
=
(
unsigned
char
*
)(
header
+
1
);
unsigned
char
*
p
=
(
unsigned
char
*
)(
header
+
1
);
...
@@ -1447,23 +1449,30 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
...
@@ -1447,23 +1449,30 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
int
nameoffset
;
int
nameoffset
;
unsigned
short
flag
;
unsigned
short
flag
;
int
q
,
ans
,
anscount
=
0
,
addncount
=
0
;
int
q
,
ans
,
anscount
=
0
,
addncount
=
0
;
int
dryrun
=
0
,
sec_reqd
=
0
;
int
dryrun
=
0
,
sec_reqd
=
0
,
have_pseudoheader
=
0
;
int
is_sign
;
int
is_sign
;
struct
crec
*
crecp
;
struct
crec
*
crecp
;
int
nxdomain
=
0
,
auth
=
1
,
trunc
=
0
,
sec_data
=
1
;
int
nxdomain
=
0
,
auth
=
1
,
trunc
=
0
,
sec_data
=
1
;
struct
mx_srv_record
*
rec
;
struct
mx_srv_record
*
rec
;
size_t
len
;
/* Don't return AD set even for local data if checking disabled. */
if
(
header
->
hb4
&
HB4_CD
)
sec_data
=
0
;
/* If there is an RFC2671 pseudoheader then it will be overwritten by
/* If there is an RFC2671 pseudoheader then it will be overwritten by
partial replies, so we have to do a dry run to see if we can answer
partial replies, so we have to do a dry run to see if we can answer
the query. We check to see if the do bit is set, if so we always
the query. We check to see if the do bit is set, if so we always
forward rather than answering from the cache, which doesn't include
forward rather than answering from the cache, which doesn't include
security information. */
security information
, unless we're in DNSSEC validation mode
. */
if
(
find_pseudoheader
(
header
,
qlen
,
NULL
,
&
pheader
,
&
is_sign
))
if
(
find_pseudoheader
(
header
,
qlen
,
NULL
,
&
pheader
,
&
is_sign
))
{
{
unsigned
short
udpsz
,
flags
;
unsigned
short
udpsz
,
flags
;
unsigned
char
*
psave
=
pheader
;
unsigned
char
*
psave
=
pheader
;
have_pseudoheader
=
1
;
GETSHORT
(
udpsz
,
pheader
);
GETSHORT
(
udpsz
,
pheader
);
pheader
+=
2
;
/* ext_rcode */
pheader
+=
2
;
/* ext_rcode */
GETSHORT
(
flags
,
pheader
);
GETSHORT
(
flags
,
pheader
);
...
@@ -1637,7 +1646,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
...
@@ -1637,7 +1646,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
!
dryrun
)
if
(
!
dryrun
)
log_query
(
crecp
->
flags
&
~
F_FORWARD
,
name
,
&
addr
,
NULL
);
log_query
(
crecp
->
flags
&
~
F_FORWARD
,
name
,
&
addr
,
NULL
);
}
}
else
if
((
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
))
||
!
sec_reqd
)
else
if
((
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
))
||
!
sec_reqd
||
option_bool
(
OPT_DNSSEC_VALID
)
)
{
{
ans
=
1
;
ans
=
1
;
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
)))
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
)))
...
@@ -1834,7 +1843,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
...
@@ -1834,7 +1843,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
!
dryrun
)
if
(
!
dryrun
)
log_query
(
crecp
->
flags
,
name
,
NULL
,
NULL
);
log_query
(
crecp
->
flags
,
name
,
NULL
,
NULL
);
}
}
else
if
((
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
))
||
!
sec_reqd
)
else
if
((
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
))
||
!
sec_reqd
||
option_bool
(
OPT_DNSSEC_VALID
)
)
{
{
/* If we are returning local answers depending on network,
/* If we are returning local answers depending on network,
filter here. */
filter here. */
...
@@ -2060,12 +2069,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
...
@@ -2060,12 +2069,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
trunc
)
if
(
trunc
)
header
->
hb3
|=
HB3_TC
;
header
->
hb3
|=
HB3_TC
;
header
->
hb4
&=
~
HB4_AD
;
if
(
option_bool
(
OPT_DNSSEC_VALID
)
||
option_bool
(
OPT_DNSSEC_PROXY
))
if
(
sec_data
)
header
->
hb4
|=
HB4_AD
;
if
(
nxdomain
)
if
(
nxdomain
)
SET_RCODE
(
header
,
NXDOMAIN
);
SET_RCODE
(
header
,
NXDOMAIN
);
else
else
...
@@ -2073,6 +2076,18 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
...
@@ -2073,6 +2076,18 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
header
->
ancount
=
htons
(
anscount
);
header
->
ancount
=
htons
(
anscount
);
header
->
nscount
=
htons
(
0
);
header
->
nscount
=
htons
(
0
);
header
->
arcount
=
htons
(
addncount
);
header
->
arcount
=
htons
(
addncount
);
return
ansp
-
(
unsigned
char
*
)
header
;
header
->
hb4
&=
~
HB4_AD
;
len
=
ansp
-
(
unsigned
char
*
)
header
;
if
(
have_pseudoheader
)
{
len
=
add_pseudoheader
(
header
,
len
,
(
unsigned
char
*
)
limit
,
0
,
NULL
,
0
,
sec_reqd
);
if
(
sec_reqd
&&
sec_data
)
header
->
hb4
|=
HB4_AD
;
}
return
len
;
}
}
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