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
8a9be9e4
Commit
8a9be9e4
authored
Jan 25, 2014
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace CRC32 with SHA1 for spoof detection in DNSSEC builds.
parent
c92f0083
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
93 additions
and
26 deletions
+93
-26
src/dnsmasq.h
src/dnsmasq.h
+9
-2
src/dnssec.c
src/dnssec.c
+30
-0
src/forward.c
src/forward.c
+54
-24
No files found.
src/dnsmasq.h
View file @
8a9be9e4
...
...
@@ -539,6 +539,12 @@ struct hostsfile {
#define FREC_DNSKEY_QUERY 8
#define FREC_DS_QUERY 16
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20
/* SHA-1 digest size */
#else
#define HASH_SIZE sizeof(int)
#endif
struct
frec
{
union
mysockaddr
source
;
struct
all_addr
dest
;
...
...
@@ -550,9 +556,9 @@ struct frec {
unsigned
int
iface
;
unsigned
short
orig_id
,
new_id
;
int
fd
,
forwardall
,
flags
;
unsigned
int
crc
;
time_t
time
;
#ifdef HAVE_DNSSEC
unsigned
char
*
hash
[
HASH_SIZE
];
#ifdef HAVE_DNSSEC
int
class
;
struct
blockdata
*
stash
;
/* Saved reply, whilst we validate */
size_t
stash_len
;
...
...
@@ -1070,6 +1076,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char
int
dnssec_validate_ds
(
time_t
now
,
struct
dns_header
*
header
,
size_t
plen
,
char
*
name
,
char
*
keyname
,
int
class
);
int
dnssec_validate_reply
(
time_t
now
,
struct
dns_header
*
header
,
size_t
plen
,
char
*
name
,
char
*
keyname
,
int
*
class
);
int
dnskey_keytag
(
int
alg
,
int
flags
,
unsigned
char
*
rdata
,
int
rdlen
);
unsigned
char
*
hash_questions
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
name
);
/* util.c */
void
rand_init
(
void
);
...
...
src/dnssec.c
View file @
8a9be9e4
...
...
@@ -1366,5 +1366,35 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
return
add_do_bit
(
header
,
p
-
(
unsigned
char
*
)
header
,
end
);
}
unsigned
char
*
hash_questions
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
name
)
{
int
q
;
unsigned
int
len
;
unsigned
char
*
p
=
(
unsigned
char
*
)(
header
+
1
);
const
struct
nettle_hash
*
hash
;
void
*
ctx
;
unsigned
char
*
digest
;
if
(
!
(
hash
=
hash_find
(
"sha1"
))
||
!
hash_init
(
hash
,
&
ctx
,
&
digest
))
return
NULL
;
for
(
q
=
ntohs
(
header
->
qdcount
);
q
!=
0
;
q
--
)
{
if
(
!
extract_name
(
header
,
plen
,
&
p
,
name
,
1
,
4
))
return
digest
;
/* bad packet */
len
=
to_wire
(
name
);
hash
->
update
(
ctx
,
len
,
(
unsigned
char
*
)
name
);
/* CRC the class and type as well */
hash
->
update
(
ctx
,
4
,
p
);
p
+=
4
;
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
0
))
return
digest
;
/* bad packet */
}
return
digest
;
}
#endif
/* HAVE_DNSSEC */
src/forward.c
View file @
8a9be9e4
...
...
@@ -16,11 +16,11 @@
#include "dnsmasq.h"
static
struct
frec
*
lookup_frec
(
unsigned
short
id
,
unsigned
int
crc
);
static
struct
frec
*
lookup_frec
(
unsigned
short
id
,
void
*
hash
);
static
struct
frec
*
lookup_frec_by_sender
(
unsigned
short
id
,
union
mysockaddr
*
addr
,
unsigned
int
crc
);
static
unsigned
short
get_id
(
unsigned
int
crc
);
void
*
hash
);
static
unsigned
short
get_id
(
void
);
static
void
free_frec
(
struct
frec
*
f
);
static
struct
randfd
*
allocate_rfd
(
int
family
);
...
...
@@ -239,18 +239,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
char
*
domain
=
NULL
;
int
type
=
0
,
norebind
=
0
;
struct
all_addr
*
addrp
=
NULL
;
unsigned
int
crc
=
questions_crc
(
header
,
plen
,
daemon
->
namebuff
);
unsigned
int
flags
=
0
;
unsigned
int
gotname
=
extract_request
(
header
,
plen
,
daemon
->
namebuff
,
NULL
);
struct
server
*
start
=
NULL
;
#ifdef HAVE_DNSSEC
void
*
hash
=
hash_questions
(
header
,
plen
,
daemon
->
namebuff
);
#else
unsigned
int
crc
=
questions_crc
(
header
,
plen
,
daemon
->
namebuff
);
void
*
hash
=
&
crc
;
#endif
unsigned
int
gotname
=
extract_request
(
header
,
plen
,
daemon
->
namebuff
,
NULL
);
/* RFC 4035: sect 4.6 para 2 */
header
->
hb4
&=
~
HB4_AD
;
/* may be no servers available. */
if
(
!
daemon
->
servers
)
forward
=
NULL
;
else
if
(
forward
||
(
forward
=
lookup_frec_by_sender
(
ntohs
(
header
->
id
),
udpaddr
,
crc
)))
else
if
(
forward
||
(
hash
&&
(
forward
=
lookup_frec_by_sender
(
ntohs
(
header
->
id
),
udpaddr
,
hash
)
)))
{
#ifdef HAVE_DNSSEC
/* If we've already got an answer to this query, but we're awaiting keys for vaildation,
...
...
@@ -320,9 +325,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward
->
dest
=
*
dst_addr
;
forward
->
iface
=
dst_iface
;
forward
->
orig_id
=
ntohs
(
header
->
id
);
forward
->
new_id
=
get_id
(
crc
);
forward
->
new_id
=
get_id
();
forward
->
fd
=
udpfd
;
forward
->
crc
=
crc
;
memcpy
(
forward
->
hash
,
hash
,
HASH_SIZE
)
;
forward
->
forwardall
=
0
;
forward
->
flags
=
0
;
if
(
norebind
)
...
...
@@ -653,7 +658,11 @@ void reply_query(int fd, int family, time_t now)
ssize_t
n
=
recvfrom
(
fd
,
daemon
->
packet
,
daemon
->
packet_buff_sz
,
0
,
&
serveraddr
.
sa
,
&
addrlen
);
size_t
nn
;
struct
server
*
server
;
void
*
hash
;
#ifndef HAVE_DNSSEC
unsigned
int
crc
;
#endif
/* packet buffer overwritten */
daemon
->
srv_save
=
NULL
;
...
...
@@ -671,10 +680,17 @@ void reply_query(int fd, int family, time_t now)
break
;
header
=
(
struct
dns_header
*
)
daemon
->
packet
;
#ifdef HAVE_DNSSEC
hash
=
hash_questions
(
header
,
n
,
daemon
->
namebuff
);
#else
hash
=
&
crc
;
crc
=
questions_crc
(
header
,
n
,
daemon
->
namebuff
);
#endif
if
(
!
server
||
n
<
(
int
)
sizeof
(
struct
dns_header
)
||
!
(
header
->
hb3
&
HB3_QR
)
||
!
(
forward
=
lookup_frec
(
ntohs
(
header
->
id
),
questions_crc
(
header
,
n
,
daemon
->
namebuff
)
)))
!
(
forward
=
lookup_frec
(
ntohs
(
header
->
id
),
hash
)))
return
;
if
((
RCODE
(
header
)
==
SERVFAIL
||
RCODE
(
header
)
==
REFUSED
)
&&
...
...
@@ -813,8 +829,9 @@ void reply_query(int fd, int family, time_t now)
nn
=
dnssec_generate_query
(
header
,((
char
*
)
header
)
+
daemon
->
packet_buff_sz
,
daemon
->
keyname
,
forward
->
class
,
T_DS
,
&
server
->
addr
);
}
new
->
crc
=
questions_crc
(
header
,
nn
,
daemon
->
namebuff
);
new
->
new_id
=
get_id
(
new
->
crc
);
if
((
hash
=
hash_questions
(
header
,
nn
,
daemon
->
namebuff
)))
memcpy
(
new
->
hash
,
hash
,
HASH_SIZE
);
new
->
new_id
=
get_id
();
header
->
id
=
htons
(
new
->
new_id
);
/* Save query for retransmission */
new
->
stash
=
blockdata_alloc
((
char
*
)
header
,
nn
);
...
...
@@ -1357,8 +1374,13 @@ unsigned char *tcp_request(int confd, time_t now,
if
(
!
flags
&&
last_server
)
{
struct
server
*
firstsendto
=
NULL
;
#ifdef HAVE_DNSSEC
unsigned
char
*
newhash
,
*
hash
[
HASH_SIZE
];
if
((
newhash
=
hash_questions
(
header
,
(
unsigned
int
)
size
,
daemon
->
keyname
)))
memcpy
(
hash
,
newhash
,
HASH_SIZE
);
#else
unsigned
int
crc
=
questions_crc
(
header
,
(
unsigned
int
)
size
,
daemon
->
namebuff
);
#endif
/* Loop round available servers until we succeed in connecting to one.
Note that this code subtley ensures that consecutive queries on this connection
which can go to the same server, do so. */
...
...
@@ -1481,10 +1503,18 @@ unsigned char *tcp_request(int confd, time_t now,
/* If the crc of the question section doesn't match the crc we sent, then
someone might be attempting to insert bogus values into the cache by
sending replies containing questions and bogus answers. */
if
(
crc
==
questions_crc
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
))
m
=
process_reply
(
header
,
now
,
last_server
,
(
unsigned
int
)
m
,
option_bool
(
OPT_NO_REBIND
)
&&
!
norebind
,
no_cache_dnssec
,
cache_secure
,
check_subnet
,
&
peer_addr
);
#ifdef HAVE_DNSSEC
newhash
=
hash_questions
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
);
if
(
!
newhash
||
memcmp
(
hash
,
newhash
,
HASH_SIZE
)
!=
0
)
break
;
#else
if
(
crc
!=
questions_crc
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
))
break
;
#endif
m
=
process_reply
(
header
,
now
,
last_server
,
(
unsigned
int
)
m
,
option_bool
(
OPT_NO_REBIND
)
&&
!
norebind
,
no_cache_dnssec
,
cache_secure
,
check_subnet
,
&
peer_addr
);
break
;
}
...
...
@@ -1674,13 +1704,13 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
}
/* crc is all-ones if not known. */
static
struct
frec
*
lookup_frec
(
unsigned
short
id
,
unsigned
int
crc
)
static
struct
frec
*
lookup_frec
(
unsigned
short
id
,
void
*
hash
)
{
struct
frec
*
f
;
for
(
f
=
daemon
->
frec_list
;
f
;
f
=
f
->
next
)
if
(
f
->
sentto
&&
f
->
new_id
==
id
&&
(
f
->
crc
==
crc
||
crc
==
0xffffffff
))
(
!
hash
||
memcmp
(
hash
,
f
->
hash
,
HASH_SIZE
)
==
0
))
return
f
;
return
NULL
;
...
...
@@ -1688,14 +1718,14 @@ static struct frec *lookup_frec(unsigned short id, unsigned int crc)
static
struct
frec
*
lookup_frec_by_sender
(
unsigned
short
id
,
union
mysockaddr
*
addr
,
unsigned
int
crc
)
void
*
hash
)
{
struct
frec
*
f
;
for
(
f
=
daemon
->
frec_list
;
f
;
f
=
f
->
next
)
if
(
f
->
sentto
&&
f
->
orig_id
==
id
&&
f
->
crc
==
crc
&&
memcmp
(
hash
,
f
->
hash
,
HASH_SIZE
)
==
0
&&
sockaddr_isequal
(
&
f
->
source
,
addr
))
return
f
;
...
...
@@ -1719,13 +1749,13 @@ void server_gone(struct server *server)
}
/* return unique random ids. */
static
unsigned
short
get_id
(
unsigned
int
crc
)
static
unsigned
short
get_id
(
void
)
{
unsigned
short
ret
=
0
;
do
ret
=
rand16
();
while
(
lookup_frec
(
ret
,
crc
));
while
(
lookup_frec
(
ret
,
NULL
));
return
ret
;
}
...
...
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