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
0975a58e
Commit
0975a58e
authored
Jan 15, 2014
by
Simon Kelley
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
ssh://central/var/cache/git/dnsmasq
parents
a59ff5f3
a25720a3
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
361 additions
and
529 deletions
+361
-529
Makefile
Makefile
+15
-15
src/blockdata.c
src/blockdata.c
+23
-24
src/dns-protocol.h
src/dns-protocol.h
+0
-18
src/dnsmasq.h
src/dnsmasq.h
+3
-3
src/dnssec-crypto.h
src/dnssec-crypto.h
+0
-83
src/dnssec-openssl.c
src/dnssec-openssl.c
+0
-316
src/dnssec.c
src/dnssec.c
+257
-46
src/forward.c
src/forward.c
+26
-2
src/option.c
src/option.c
+4
-4
src/rfc1035.c
src/rfc1035.c
+33
-18
No files found.
Makefile
View file @
0975a58e
...
...
@@ -51,33 +51,33 @@ top!=pwd
# GNU make way.
top
?=
$(CURDIR)
dbus_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--cflags
dbus-1
`
dbus_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--libs
dbus-1
`
idn_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--cflags
libidn
`
idn_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--libs
libidn
`
ct_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--cflags
libnetfilter_conntrack
`
ct_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--libs
libnetfilter_conntrack
`
lua_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--cflags
lua5.1
`
lua_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--libs
lua5.1
`
sec_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--cflags
libcrypto
`
sec_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--libs
libcrypto
`
sunos_libs
=
`
if
uname
|
grep
SunOS
>
/dev/null 2>&1
;
then
echo
-lsocket
-lnsl
-lposix4
;
fi
`
dbus_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--cflags
dbus-1
`
dbus_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DBUS
$(PKG_CONFIG)
--libs
dbus-1
`
idn_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--cflags
libidn
`
idn_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_IDN
$(PKG_CONFIG)
--libs
libidn
`
ct_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--cflags
libnetfilter_conntrack
`
ct_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_CONNTRACK
$(PKG_CONFIG)
--libs
libnetfilter_conntrack
`
lua_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--cflags
lua5.1
`
lua_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_LUASCRIPT
$(PKG_CONFIG)
--libs
lua5.1
`
nettle_cflags
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--cflags
nettle hogweed
`
nettle_libs
=
`
echo
$(COPTS)
|
$(top)
/bld/pkg-wrapper HAVE_DNSSEC
$(PKG_CONFIG)
--libs
nettle hogweed
`
sunos_libs
=
`
if
uname
|
grep
SunOS
>
/dev/null 2>&1
;
then
echo
-lsocket
-lnsl
-lposix4
;
fi
`
version
=
-DVERSION
=
'\"`
$(top)
/bld/get-version
$(top)
`\"'
objs
=
cache.o rfc1035.o util.o option.o forward.o network.o
\
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o
\
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o
\
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
\
domain.o dnssec.o
dnssec-openssl.o
blockdata.o
domain.o dnssec.o blockdata.o
hdrs
=
dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h
\
dns-protocol.h radv-protocol.h
dns-protocol.h radv-protocol.h
ip6addr.h
all
:
$(BUILDDIR)
@
cd
$(BUILDDIR)
&&
$(MAKE)
\
top
=
"
$(top)
"
\
build_cflags
=
"
$(version)
$(dbus_cflags)
$(idn_cflags)
$(ct_cflags)
$(lua_cflags)
$(
sec
_cflags)
"
\
build_libs
=
"
$(dbus_libs)
$(idn_libs)
$(ct_libs)
$(lua_libs)
$(sunos_libs)
$(
sec
_libs)
"
\
build_cflags
=
"
$(version)
$(dbus_cflags)
$(idn_cflags)
$(ct_cflags)
$(lua_cflags)
$(
nettle
_cflags)
"
\
build_libs
=
"
$(dbus_libs)
$(idn_libs)
$(ct_libs)
$(lua_libs)
$(sunos_libs)
$(
nettle
_libs)
"
\
-f
$(top)
/Makefile dnsmasq
mostly_clean
:
...
...
src/blockdata.c
View file @
0975a58e
...
...
@@ -67,21 +67,6 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
return
ret
;
}
size_t
blockdata_walk
(
struct
blockdata
**
key
,
unsigned
char
**
p
,
size_t
cnt
)
{
if
(
*
p
==
NULL
)
*
p
=
(
*
key
)
->
key
;
else
if
(
*
p
==
(
*
key
)
->
key
+
KEYBLOCK_LEN
)
{
*
key
=
(
*
key
)
->
next
;
if
(
*
key
==
NULL
)
return
0
;
*
p
=
(
*
key
)
->
key
;
}
return
MIN
(
cnt
,
(
size_t
)((
*
key
)
->
key
+
KEYBLOCK_LEN
-
(
*
p
)));
}
void
blockdata_free
(
struct
blockdata
*
blocks
)
{
struct
blockdata
*
tmp
;
...
...
@@ -96,24 +81,38 @@ void blockdata_free(struct blockdata *blocks)
}
}
/*
copy blocks into data[], return 1 if data[] unchanged by so doing
*/
int
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
)
/*
if data == NULL, return pointer to static block of sufficient size
*/
void
*
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
)
{
size_t
blen
;
struct
blockdata
*
b
;
int
match
=
1
;
void
*
new
,
*
d
;
for
(
b
=
block
;
len
>
0
&&
b
;
b
=
b
->
next
)
static
unsigned
int
buff_len
=
0
;
static
unsigned
char
*
buff
=
NULL
;
if
(
!
data
)
{
if
(
len
>
buff_len
)
{
if
(
!
(
new
=
whine_malloc
(
len
)))
return
NULL
;
if
(
buff
)
free
(
buff
);
buff
=
new
;
}
data
=
buff
;
}
for
(
d
=
data
,
b
=
block
;
len
>
0
&&
b
;
b
=
b
->
next
)
{
blen
=
len
>
KEYBLOCK_LEN
?
KEYBLOCK_LEN
:
len
;
if
(
memcmp
(
data
,
b
->
key
,
blen
)
!=
0
)
match
=
0
;
memcpy
(
data
,
b
->
key
,
blen
);
data
+=
blen
;
memcpy
(
d
,
b
->
key
,
blen
);
d
+=
blen
;
len
-=
blen
;
}
return
match
;
return
data
;
}
#endif
src/dns-protocol.h
View file @
0975a58e
...
...
@@ -136,24 +136,6 @@ struct dns_header {
(cp) += 4; \
}
#define CHECKED_GETCHAR(var, ptr, len) do { \
if ((len) < 1) return 0; \
var = *ptr++; \
(len) -= 1; \
} while (0)
#define CHECKED_GETSHORT(var, ptr, len) do { \
if ((len) < 2) return 0; \
GETSHORT(var, ptr); \
(len) -= 2; \
} while (0)
#define CHECKED_GETLONG(var, ptr, len) do { \
if ((len) < 4) return 0; \
GETLONG(var, ptr); \
(len) -= 4; \
} while (0)
#define CHECK_LEN(header, pp, plen, len) \
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
...
...
src/dnsmasq.h
View file @
0975a58e
...
...
@@ -230,7 +230,8 @@ struct event_desc {
#define OPT_QUIET_DHCP6 43
#define OPT_QUIET_RA 44
#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
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
...
...
@@ -993,8 +994,7 @@ struct crec *cache_enumerate(int init);
#ifdef HAVE_DNSSEC
void
blockdata_report
(
void
);
struct
blockdata
*
blockdata_alloc
(
char
*
data
,
size_t
len
);
size_t
blockdata_walk
(
struct
blockdata
**
key
,
unsigned
char
**
p
,
size_t
cnt
);
int
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
);
void
*
blockdata_retrieve
(
struct
blockdata
*
block
,
size_t
len
,
void
*
data
);
void
blockdata_free
(
struct
blockdata
*
blocks
);
#endif
...
...
src/dnssec-crypto.h
deleted
100644 → 0
View file @
a59ff5f3
/* dnssec-crypto.h is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DNSSEC_CRYPTO_H
#define DNSSEC_CRYPTO_H
struct
blockdata
;
/*
* vtable for a signature verification algorithm.
*
* Each algorithm verifies that a certain signature over a (possibly non-contigous)
* array of data has been made with the specified key.
*
* Sample of usage:
*
* // First, set the signature we need to check. Notice: data is not copied
* // nor consumed, so the pointer must stay valid.
* alg->set_signature(sig, 16);
*
* // Second, get push the data through the corresponding digest algorithm;
* // data is consumed immediately, so the buffers can be freed or modified.
* digestalg_begin(alg->get_digestalgo());
* digestalg_add_data(buf1, 123);
* digestalg_add_data(buf2, 45);
* digestalg_add_data(buf3, 678);
* alg->set_digest(digestalg_final());
*
* // Third, verify if we got the correct key for this signature.
* alg->verify(key1, 16);
* alg->verify(key2, 16);
*/
typedef
struct
VerifyAlgCtx
VerifyAlgCtx
;
typedef
struct
{
int
digest_algo
;
int
(
*
verify
)(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key
,
unsigned
key_len
);
}
VerifyAlg
;
struct
VerifyAlgCtx
{
const
VerifyAlg
*
vtbl
;
unsigned
char
*
sig
;
size_t
siglen
;
unsigned
char
digest
[
64
];
/* TODO: if memory problems, use VLA */
};
int
verifyalg_supported
(
int
algo
);
VerifyAlgCtx
*
verifyalg_alloc
(
int
algo
);
void
verifyalg_free
(
VerifyAlgCtx
*
a
);
int
verifyalg_algonum
(
VerifyAlgCtx
*
a
);
/* Functions to calculate the digest of a key */
/* RFC4034 digest algorithms */
#define DIGESTALG_SHA1 1
#define DIGESTALG_SHA256 2
#define DIGESTALG_MD5 256
#define DIGESTALG_SHA512 257
int
digestalg_supported
(
int
algo
);
void
digestalg_begin
(
int
algo
);
void
digestalg_add_data
(
void
*
data
,
unsigned
len
);
void
digestalg_add_keydata
(
struct
blockdata
*
key
,
size_t
len
);
unsigned
char
*
digestalg_final
(
void
);
int
digestalg_len
(
void
);
#endif
/* DNSSEC_CRYPTO_H */
src/dnssec-openssl.c
deleted
100644 → 0
View file @
a59ff5f3
/* dnssec-openssl.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_DNSSEC
#include "dnssec-crypto.h"
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include <string.h>
#define POOL_SIZE 1
static
union
_Pool
{
VerifyAlgCtx
ctx
;
}
Pool
[
POOL_SIZE
];
static
char
pool_used
=
0
;
static
void
print_hex
(
unsigned
char
*
data
,
unsigned
len
)
{
while
(
len
>
0
)
{
printf
(
"%02x"
,
*
data
++
);
--
len
;
}
printf
(
"
\n
"
);
}
static
int
keydata_to_bn
(
BIGNUM
*
ret
,
struct
blockdata
**
key_data
,
unsigned
char
**
p
,
unsigned
len
)
{
size_t
cnt
;
BIGNUM
temp
;
BN_init
(
ret
);
cnt
=
blockdata_walk
(
key_data
,
p
,
len
);
BN_bin2bn
(
*
p
,
cnt
,
ret
);
len
-=
cnt
;
*
p
+=
cnt
;
while
(
len
>
0
)
{
if
(
!
(
cnt
=
blockdata_walk
(
key_data
,
p
,
len
)))
return
0
;
BN_lshift
(
ret
,
ret
,
cnt
*
8
);
BN_init
(
&
temp
);
BN_bin2bn
(
*
p
,
cnt
,
&
temp
);
BN_add
(
ret
,
ret
,
&
temp
);
len
-=
cnt
;
*
p
+=
cnt
;
}
return
1
;
}
static
int
rsasha1_parse_key
(
BIGNUM
*
exp
,
BIGNUM
*
mod
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
unsigned
char
*
p
=
key_data
->
key
;
size_t
exp_len
,
mod_len
;
CHECKED_GETCHAR
(
exp_len
,
p
,
key_len
);
if
(
exp_len
==
0
)
CHECKED_GETSHORT
(
exp_len
,
p
,
key_len
);
if
(
exp_len
>=
key_len
)
return
0
;
mod_len
=
key_len
-
exp_len
;
return
keydata_to_bn
(
exp
,
&
key_data
,
&
p
,
exp_len
)
&&
keydata_to_bn
(
mod
,
&
key_data
,
&
p
,
mod_len
);
}
static
int
dsasha1_parse_key
(
BIGNUM
*
Q
,
BIGNUM
*
P
,
BIGNUM
*
G
,
BIGNUM
*
Y
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
unsigned
char
*
p
=
key_data
->
key
;
int
T
;
CHECKED_GETCHAR
(
T
,
p
,
key_len
);
return
keydata_to_bn
(
Q
,
&
key_data
,
&
p
,
20
)
&&
keydata_to_bn
(
P
,
&
key_data
,
&
p
,
64
+
T
*
8
)
&&
keydata_to_bn
(
G
,
&
key_data
,
&
p
,
64
+
T
*
8
)
&&
keydata_to_bn
(
Y
,
&
key_data
,
&
p
,
64
+
T
*
8
);
}
static
int
rsa_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
,
int
nid
,
int
dlen
)
{
int
validated
=
0
;
RSA
*
rsa
=
RSA_new
();
rsa
->
e
=
BN_new
();
rsa
->
n
=
BN_new
();
if
(
rsasha1_parse_key
(
rsa
->
e
,
rsa
->
n
,
key_data
,
key_len
)
&&
RSA_verify
(
nid
,
ctx
->
digest
,
dlen
,
ctx
->
sig
,
ctx
->
siglen
,
rsa
))
validated
=
1
;
RSA_free
(
rsa
);
return
validated
;
}
static
int
rsamd5_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_md5
,
16
);
}
static
int
rsasha1_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha1
,
20
);
}
static
int
rsasha256_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha256
,
32
);
}
static
int
rsasha512_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
return
rsa_verify
(
ctx
,
key_data
,
key_len
,
NID_sha512
,
64
);
}
static
int
dsasha1_verify
(
VerifyAlgCtx
*
ctx
,
struct
blockdata
*
key_data
,
unsigned
key_len
)
{
static
unsigned
char
asn1_signature
[]
=
{
0x30
,
0x2E
,
// sequence
0x02
,
21
,
// large integer (21 bytes)
0x00
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
// R
0x02
,
21
,
// large integer (21 bytes)
0x00
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
// S
};
int
validated
=
0
;
/* A DSA signature is made of 2 bignums (R & S). We could parse them manually with BN_bin2bn(),
but OpenSSL does not have an API to verify a DSA signature given R and S, and insists
in having a ASN.1 BER sequence (as per RFC3279).
We prepare a hard-coded ASN.1 sequence, and just fill in the R&S numbers in it. */
memcpy
(
asn1_signature
+
5
,
ctx
->
sig
+
1
,
20
);
memcpy
(
asn1_signature
+
28
,
ctx
->
sig
+
21
,
20
);
DSA
*
dsa
=
DSA_new
();
dsa
->
q
=
BN_new
();
dsa
->
p
=
BN_new
();
dsa
->
g
=
BN_new
();
dsa
->
pub_key
=
BN_new
();
if
(
dsasha1_parse_key
(
dsa
->
q
,
dsa
->
p
,
dsa
->
g
,
dsa
->
pub_key
,
key_data
,
key_len
)
&&
DSA_verify
(
0
,
ctx
->
digest
,
20
,
asn1_signature
,
countof
(
asn1_signature
),
dsa
)
>
0
)
validated
=
1
;
DSA_free
(
dsa
);
return
validated
;
}
#define VALG_UNSUPPORTED() { \
0,0 \
}
/**/
#define VALG_VTABLE(alg, digest) { \
digest, \
alg ## _verify \
}
/**/
/* Updated registry that merges various RFCs:
https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml */
static
const
VerifyAlg
valgs
[]
=
{
VALG_UNSUPPORTED
(),
/* 0: reserved */
VALG_VTABLE
(
rsamd5
,
DIGESTALG_MD5
),
/* 1: RSAMD5 */
VALG_UNSUPPORTED
(),
/* 2: DH */
VALG_VTABLE
(
dsasha1
,
DIGESTALG_SHA1
),
/* 3: DSA */
VALG_UNSUPPORTED
(),
/* 4: ECC */
VALG_VTABLE
(
rsasha1
,
DIGESTALG_SHA1
),
/* 5: RSASHA1 */
VALG_VTABLE
(
dsasha1
,
DIGESTALG_SHA1
),
/* 6: DSA-NSEC3-SHA1 */
VALG_VTABLE
(
rsasha1
,
DIGESTALG_SHA1
),
/* 7: RSASHA1-NSEC3-SHA1 */
VALG_VTABLE
(
rsasha256
,
DIGESTALG_SHA256
),
/* 8: RSASHA256 */
VALG_UNSUPPORTED
(),
/* 9: unassigned */
VALG_VTABLE
(
rsasha512
,
DIGESTALG_SHA512
),
/* 10: RSASHA512 */
VALG_UNSUPPORTED
(),
/* 11: unassigned */
VALG_UNSUPPORTED
(),
/* 12: ECC-GOST */
VALG_UNSUPPORTED
(),
/* 13: ECDSAP256SHA256 */
VALG_UNSUPPORTED
(),
/* 14: ECDSAP384SHA384 */
};
/* TODO: remove if we don't need this anymore
(to be rechecked if we ever remove OpenSSL) */
static
const
int
valgctx_size
[]
=
{
0
,
/* 0: reserved */
sizeof
(
VerifyAlgCtx
),
/* 1: RSAMD5 */
0
,
/* 2: DH */
sizeof
(
VerifyAlgCtx
),
/* 3: DSA */
0
,
/* 4: ECC */
sizeof
(
VerifyAlgCtx
),
/* 5: RSASHA1 */
sizeof
(
VerifyAlgCtx
),
/* 6: DSA-NSEC3-SHA1 */
sizeof
(
VerifyAlgCtx
),
/* 7: RSASHA1-NSEC3-SHA1 */
sizeof
(
VerifyAlgCtx
),
/* 8: RSASHA256 */
0
,
/* 9: unassigned */
sizeof
(
VerifyAlgCtx
),
/* 10: RSASHA512 */
0
,
/* 11: unassigned */
0
,
/* 12: ECC-GOST */
0
,
/* 13: ECDSAP256SHA256 */
0
,
/* 14: ECDSAP384SHA384 */
};
int
verifyalg_supported
(
int
algo
)
{
return
(
algo
<
countof
(
valgctx_size
)
&&
valgctx_size
[
algo
]
!=
0
);
}
VerifyAlgCtx
*
verifyalg_alloc
(
int
algo
)
{
int
i
;
VerifyAlgCtx
*
ret
=
0
;
if
(
pool_used
==
(
1
<<
POOL_SIZE
)
-
1
)
ret
=
whine_malloc
(
valgctx_size
[
algo
]);
else
for
(
i
=
0
;
i
<
POOL_SIZE
;
++
i
)
if
(
!
(
pool_used
&
(
1
<<
i
)))
{
ret
=
(
VerifyAlgCtx
*
)
&
Pool
[
i
];
pool_used
|=
1
<<
i
;
break
;
}
if
(
ret
)
ret
->
vtbl
=
&
valgs
[
algo
];
return
ret
;
}
void
verifyalg_free
(
VerifyAlgCtx
*
a
)
{
int
pool_idx
=
((
char
*
)
a
-
(
char
*
)
&
Pool
[
0
])
/
sizeof
(
Pool
[
0
]);
if
(
pool_idx
<
0
||
pool_idx
>=
POOL_SIZE
)
{
free
(
a
);
return
;
}
pool_used
&=
~
(
1
<<
pool_idx
);
}
int
verifyalg_algonum
(
VerifyAlgCtx
*
a
)
{
int
num
=
a
->
vtbl
-
valgs
;
if
(
num
<
0
||
num
>=
countof
(
valgs
))
return
-
1
;
return
num
;
}
static
EVP_MD_CTX
digctx
;
int
digestalg_supported
(
int
algo
)
{
return
(
algo
==
DIGESTALG_SHA1
||
algo
==
DIGESTALG_SHA256
||
algo
==
DIGESTALG_MD5
||
algo
==
DIGESTALG_SHA512
);
}
void
digestalg_begin
(
int
algo
)
{
EVP_MD_CTX_init
(
&
digctx
);
if
(
algo
==
DIGESTALG_SHA1
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha1
(),
NULL
);
else
if
(
algo
==
DIGESTALG_SHA256
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha256
(),
NULL
);
else
if
(
algo
==
DIGESTALG_SHA512
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_sha512
(),
NULL
);
else
if
(
algo
==
DIGESTALG_MD5
)
EVP_DigestInit_ex
(
&
digctx
,
EVP_md5
(),
NULL
);
}
int
digestalg_len
()
{
return
EVP_MD_CTX_size
(
&
digctx
);
}
void
digestalg_add_data
(
void
*
data
,
unsigned
len
)
{
EVP_DigestUpdate
(
&
digctx
,
data
,
len
);
}
void
digestalg_add_keydata
(
struct
blockdata
*
key
,
size_t
len
)
{
size_t
cnt
;
unsigned
char
*
p
=
NULL
;
while
(
len
)
{
cnt
=
blockdata_walk
(
&
key
,
&
p
,
len
);
EVP_DigestUpdate
(
&
digctx
,
p
,
cnt
);
p
+=
cnt
;
len
-=
cnt
;
}
}
unsigned
char
*
digestalg_final
(
void
)
{
static
unsigned
char
digest
[
32
];
EVP_DigestFinal
(
&
digctx
,
digest
,
NULL
);
return
digest
;
}
#endif
/* HAVE_DNSSEC */
src/dnssec.c
View file @
0975a58e
...
...
@@ -19,13 +19,210 @@
#ifdef HAVE_DNSSEC
#include "dnssec-crypto.h"
#include <nettle/rsa.h>
#include <nettle/dsa.h>
#include <nettle/nettle-meta.h>
#include <gmp.h>
#define SERIAL_UNDEF -100
#define SERIAL_EQ 0
#define SERIAL_LT -1
#define SERIAL_GT 1
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
static
char
*
ds_digest_name
(
int
digest
)
{
switch
(
digest
)
{
case
1
:
return
"sha1"
;
case
2
:
return
"sha256"
;
case
3
:
return
"gosthash94"
;
case
4
:
return
"sha384"
;
default:
return
NULL
;
}
}
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
static
char
*
algo_digest_name
(
int
algo
)
{
switch
(
algo
)
{
case
1
:
return
"md5"
;
case
3
:
return
"sha1"
;
case
5
:
return
"sha1"
;
case
6
:
return
"sha1"
;
case
7
:
return
"sha1"
;
case
8
:
return
"sha256"
;
case
10
:
return
"sha512"
;
case
12
:
return
"gosthash94"
;
case
13
:
return
"sha256"
;
case
14
:
return
"sha384"
;
default:
return
NULL
;
}
}
/* Find pointer to correct hash function in nettle library */
static
const
struct
nettle_hash
*
hash_find
(
char
*
name
)
{
int
i
;
if
(
!
name
)
return
NULL
;
for
(
i
=
0
;
nettle_hashes
[
i
];
i
++
)
{
if
(
strcmp
(
nettle_hashes
[
i
]
->
name
,
name
)
==
0
)
return
nettle_hashes
[
i
];
}
return
NULL
;
}
/* expand ctx and digest memory allocations if necessary and init hash function */
static
int
hash_init
(
const
struct
nettle_hash
*
hash
,
void
**
ctxp
,
unsigned
char
**
digestp
)
{
static
void
*
ctx
=
NULL
;
static
unsigned
char
*
digest
=
NULL
;
static
unsigned
int
ctx_sz
=
0
;
static
unsigned
int
digest_sz
=
0
;
void
*
new
;
if
(
ctx_sz
<
hash
->
context_size
)
{
if
(
!
(
new
=
whine_malloc
(
hash
->
context_size
)))
return
0
;
if
(
ctx
)
free
(
ctx
);
ctx
=
new
;
ctx_sz
=
hash
->
context_size
;
}
if
(
digest_sz
<
hash
->
digest_size
)
{
if
(
!
(
new
=
whine_malloc
(
hash
->
digest_size
)))
return
0
;
if
(
digest
)
free
(
digest
);
digest
=
new
;
digest_sz
=
hash
->
digest_size
;
}
*
ctxp
=
ctx
;
*
digestp
=
digest
;
hash
->
init
(
ctx
);
return
1
;
}
static
int
rsa_verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
unsigned
char
*
p
;
size_t
exp_len
;
static
struct
rsa_public_key
*
key
=
NULL
;
static
mpz_t
sig_mpz
;
if
(
key
==
NULL
)
{
if
(
!
(
key
=
whine_malloc
(
sizeof
(
struct
rsa_public_key
))))
return
0
;
nettle_rsa_public_key_init
(
key
);
mpz_init
(
sig_mpz
);
}
if
((
key_len
<
3
)
||
!
(
p
=
blockdata_retrieve
(
key_data
,
key_len
,
NULL
)))
return
0
;
key_len
--
;
if
((
exp_len
=
*
p
++
)
==
0
)
{
GETSHORT
(
exp_len
,
p
);
key_len
-=
2
;
}
if
(
exp_len
>=
key_len
)
return
0
;
key
->
size
=
key_len
-
exp_len
;
mpz_import
(
key
->
e
,
exp_len
,
1
,
1
,
0
,
0
,
p
);
mpz_import
(
key
->
n
,
key
->
size
,
1
,
1
,
0
,
0
,
p
+
exp_len
);
mpz_import
(
sig_mpz
,
sig_len
,
1
,
1
,
0
,
0
,
sig
);
switch
(
algo
)
{
case
1
:
return
nettle_rsa_md5_verify_digest
(
key
,
digest
,
sig_mpz
);
case
5
:
case
7
:
return
nettle_rsa_sha1_verify_digest
(
key
,
digest
,
sig_mpz
);
case
8
:
return
nettle_rsa_sha256_verify_digest
(
key
,
digest
,
sig_mpz
);
case
10
:
return
nettle_rsa_sha512_verify_digest
(
key
,
digest
,
sig_mpz
);
}
return
0
;
}
static
int
dsa_verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
unsigned
char
*
p
;
unsigned
int
t
;
static
struct
dsa_public_key
*
key
=
NULL
;
static
struct
dsa_signature
*
sig_struct
;
if
(
key
==
NULL
)
{
if
(
!
(
sig_struct
=
whine_malloc
(
sizeof
(
struct
dsa_signature
)))
||
!
(
key
=
whine_malloc
(
sizeof
(
struct
dsa_public_key
))))
return
0
;
nettle_dsa_public_key_init
(
key
);
nettle_dsa_signature_init
(
sig_struct
);
}
if
((
sig_len
<
41
)
||
!
(
p
=
blockdata_retrieve
(
key_data
,
key_len
,
NULL
)))
return
0
;
t
=
*
p
++
;
if
(
key_len
<
(
213
+
(
t
*
24
)))
return
0
;
mpz_import
(
key
->
q
,
20
,
1
,
1
,
0
,
0
,
p
);
p
+=
20
;
mpz_import
(
key
->
p
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
key
->
g
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
key
->
y
,
64
+
(
t
*
8
),
1
,
1
,
0
,
0
,
p
);
p
+=
64
+
(
t
*
8
);
mpz_import
(
sig_struct
->
r
,
20
,
1
,
1
,
0
,
0
,
sig
+
1
);
mpz_import
(
sig_struct
->
s
,
20
,
1
,
1
,
0
,
0
,
sig
+
21
);
(
void
)
algo
;
return
nettle_dsa_sha1_verify_digest
(
key
,
digest
,
sig_struct
);
}
static
int
verify
(
struct
blockdata
*
key_data
,
unsigned
int
key_len
,
unsigned
char
*
sig
,
size_t
sig_len
,
unsigned
char
*
digest
,
int
algo
)
{
switch
(
algo
)
{
case
1
:
case
5
:
case
7
:
case
8
:
case
10
:
return
rsa_verify
(
key_data
,
key_len
,
sig
,
sig_len
,
digest
,
algo
);
case
3
:
case
6
:
return
dsa_verify
(
key_data
,
key_len
,
sig
,
sig_len
,
digest
,
algo
);
}
return
0
;
}
/* Convert from presentation format to wire format, in place.
Also map UC -> LC.
Note that using extract_name to get presentation format
...
...
@@ -362,7 +559,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if
(
type_covered
==
type
&&
check_date_range
(
sig_inception
,
sig_expiration
)
&&
verifyalg_supported
(
algo
)
&&
hash_find
(
algo_digest_name
(
algo
)
)
&&
labels
<=
name_labels
)
{
if
(
sigidx
==
sig_sz
)
...
...
@@ -404,9 +601,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* Now try all the sigs to try and find one which validates */
for
(
j
=
0
;
j
<
sigidx
;
j
++
)
{
unsigned
char
*
psav
;
int
i
,
wire_len
;
VerifyAlgCtx
*
alg
;
unsigned
char
*
psav
,
*
sig
;
int
i
,
wire_len
,
sig_len
;
const
struct
nettle_hash
*
hash
;
void
*
ctx
;
unsigned
char
*
digest
;
u32
nsigttl
;
p
=
sigs
[
j
];
...
...
@@ -427,16 +626,18 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
if
(
!
key
&&
!
(
crecp
=
cache_find_by_name
(
NULL
,
keyname
,
now
,
F_DNSKEY
)))
return
STAT_NEED_KEY
;
alg
=
verifyalg_alloc
(
algo
);
alg
->
sig
=
p
;
alg
->
siglen
=
rdlen
-
(
p
-
psav
);
sig
=
p
;
sig_len
=
rdlen
-
(
p
-
psav
);
if
(
!
(
hash
=
hash_find
(
algo_digest_name
(
algo
)))
||
!
hash_init
(
hash
,
&
ctx
,
&
digest
))
continue
;
nsigttl
=
htonl
(
orig_ttl
);
digestalg_begin
(
alg
->
vtbl
->
digest_algo
);
digestalg_add_data
(
psav
,
18
);
hash
->
update
(
ctx
,
18
,
psav
);
wire_len
=
to_wire
(
keyname
);
digestalg_add_data
(
keyname
,
wire_len
);
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
keyname
);
from_wire
(
keyname
);
for
(
i
=
0
;
i
<
rrsetidx
;
++
i
)
...
...
@@ -462,9 +663,9 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
}
wire_len
=
to_wire
(
name_start
);
digestalg_add_data
(
name_start
,
wire_len
);
digestalg_add_data
(
p
,
4
);
/* class and type */
digestalg_add_data
(
&
nsigttl
,
4
);
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
name_start
);
hash
->
update
(
ctx
,
4
,
p
);
/* class and type */
hash
->
update
(
ctx
,
4
,
(
unsigned
char
*
)
&
nsigttl
);
p
+=
8
;
/* skip class, type, ttl */
GETSHORT
(
rdlen
,
p
);
...
...
@@ -479,27 +680,27 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
for
(
len
=
0
;
(
seg
=
get_rdata
(
header
,
plen
,
end
,
name
,
&
cp
,
&
dp
))
!=
0
;
len
+=
seg
);
len
+=
end
-
cp
;
len
=
htons
(
len
);
digestalg_add_data
(
&
len
,
2
);
hash
->
update
(
ctx
,
2
,
(
unsigned
char
*
)
&
len
);
/* Now canonicalise again and digest. */
cp
=
p
;
dp
=
rr_desc
;
while
((
seg
=
get_rdata
(
header
,
plen
,
end
,
name
,
&
cp
,
&
dp
)))
digestalg_add_data
(
name
,
seg
);
hash
->
update
(
ctx
,
seg
,
(
unsigned
char
*
)
name
);
if
(
cp
!=
end
)
digestalg_add_data
(
cp
,
end
-
cp
);
hash
->
update
(
ctx
,
end
-
cp
,
cp
);
}
hash
->
digest
(
ctx
,
hash
->
digest_size
,
digest
);
/* namebuff used for workspace above, restore to leave unchanged on exit */
p
=
(
unsigned
char
*
)(
rrset
[
0
]);
extract_name
(
header
,
plen
,
&
p
,
name
,
1
,
0
);
memcpy
(
alg
->
digest
,
digestalg_final
(),
digestalg_len
());
if
(
key
)
{
if
(
algo_in
==
algo
&&
keytag_in
==
key_tag
&&
alg
->
vtbl
->
verify
(
alg
,
key
,
keylen
))
verify
(
key
,
keylen
,
sig
,
sig_len
,
digest
,
algo
))
return
STAT_SECURE
;
}
else
...
...
@@ -507,7 +708,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* iterate through all possible keys 4035 5.3.1 */
for
(;
crecp
;
crecp
=
cache_find_by_name
(
crecp
,
keyname
,
now
,
F_DNSKEY
))
if
(
crecp
->
addr
.
key
.
algo
==
algo
&&
crecp
->
addr
.
key
.
keytag
==
key_tag
&&
alg
->
vtbl
->
verify
(
alg
,
crecp
->
addr
.
key
.
keydata
,
crecp
->
uid
))
verify
(
crecp
->
addr
.
key
.
keydata
,
crecp
->
uid
,
sig
,
sig_len
,
digest
,
algo
))
return
STAT_SECURE
;
}
}
...
...
@@ -579,7 +780,6 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
psave
=
p
;
/* length at least covers flags, protocol and algo now. */
GETSHORT
(
flags
,
p
);
if
(
*
p
++
!=
3
)
return
STAT_INSECURE
;
...
...
@@ -606,30 +806,41 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
continue
;
for
(
recp1
=
crecp
;
recp1
;
recp1
=
cache_find_by_name
(
recp1
,
name
,
now
,
F_DS
))
if
(
recp1
->
addr
.
key
.
algo
==
algo
&&
recp1
->
addr
.
key
.
keytag
==
keytag
&&
(
flags
&
0x100
)
&&
/* zone key flag */
digestalg_supported
(
recp1
->
addr
.
key
.
digest
))
{
int
wire_len
=
to_wire
(
name
);
digestalg_begin
(
recp1
->
addr
.
key
.
digest
);
digestalg_add_data
(
name
,
wire_len
);
digestalg_add_data
((
char
*
)
psave
,
rdlen
);
{
void
*
ctx
;
unsigned
char
*
digest
,
*
ds_digest
;
const
struct
nettle_hash
*
hash
;
if
(
recp1
->
addr
.
key
.
algo
==
algo
&&
recp1
->
addr
.
key
.
keytag
==
keytag
&&
(
flags
&
0x100
)
&&
/* zone key flag */
(
hash
=
hash_find
(
ds_digest_name
(
recp1
->
addr
.
key
.
digest
)))
&&
hash_init
(
hash
,
&
ctx
,
&
digest
))
from_wire
(
name
);
if
(
recp1
->
uid
==
digestalg_len
()
&&
blockdata_retrieve
(
recp1
->
addr
.
key
.
keydata
,
recp1
->
uid
,
digestalg_final
())
&&
validate_rrset
(
now
,
header
,
plen
,
class
,
T_DNSKEY
,
name
,
keyname
,
key
,
rdlen
-
4
,
algo
,
keytag
))
{
struct
all_addr
a
;
valid
=
1
;
a
.
addr
.
keytag
=
keytag
;
log_query
(
F_KEYTAG
|
F_UPSTREAM
,
name
,
&
a
,
"DNSKEY keytag %u"
);
break
;
}
}
{
int
wire_len
=
to_wire
(
name
);
/* Note that digest may be different between DSs, so
we can't move this outside the loop. */
hash
->
update
(
ctx
,
(
unsigned
int
)
wire_len
,
(
unsigned
char
*
)
name
);
hash
->
update
(
ctx
,
(
unsigned
int
)
rdlen
,
psave
);
hash
->
digest
(
ctx
,
hash
->
digest_size
,
digest
);
from_wire
(
name
);
if
(
recp1
->
uid
==
(
int
)
hash
->
digest_size
&&
(
ds_digest
=
blockdata_retrieve
(
recp1
->
addr
.
key
.
keydata
,
recp1
->
uid
,
NULL
))
&&
memcmp
(
ds_digest
,
digest
,
recp1
->
uid
)
==
0
&&
validate_rrset
(
now
,
header
,
plen
,
class
,
T_DNSKEY
,
name
,
keyname
,
key
,
rdlen
-
4
,
algo
,
keytag
))
{
struct
all_addr
a
;
valid
=
1
;
a
.
addr
.
keytag
=
keytag
;
log_query
(
F_KEYTAG
|
F_UPSTREAM
,
name
,
&
a
,
"DNSKEY keytag %u"
);
break
;
}
}
}
}
if
(
valid
)
...
...
src/forward.c
View file @
0975a58e
...
...
@@ -511,7 +511,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if
(
option_bool
(
OPT_DNSSEC_VALID
))
header
->
hb4
&=
~
HB4_AD
;
if
(
cache_secure
)
if
(
!
(
header
->
hb4
&
HB4_CD
)
&&
cache_secure
)
header
->
hb4
|=
HB4_AD
;
#endif
...
...
@@ -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
nameserver info. */
...
...
@@ -824,7 +849,6 @@ void reply_query(int fd, int family, time_t now)
if
(
status
==
STAT_SECURE
)
cache_secure
=
1
;
/* TODO return SERVFAIL here */
else
if
(
status
==
STAT_BOGUS
)
no_cache_dnssec
=
1
;
...
...
src/option.c
View file @
0975a58e
...
...
@@ -140,7 +140,7 @@ struct myoption {
#define LOPT_QUIET_RA 328
#define LOPT_SEC_VALID 329
#define LOPT_DNSKEY 330
#define LOPT_DNSSEC_PERM 331
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
...
...
@@ -278,6 +278,7 @@ static const struct myoption opts[] =
{
"synth-domain"
,
1
,
0
,
LOPT_SYNTH
},
{
"dnssec"
,
0
,
0
,
LOPT_SEC_VALID
},
{
"dnskey"
,
1
,
0
,
LOPT_DNSKEY
},
{
"dnssec-permissive"
,
0
,
0
,
LOPT_DNSSEC_PERM
},
#ifdef OPTION6_PREFIX_CLASS
{
"dhcp-prefix-class"
,
1
,
0
,
LOPT_PREF_CLSS
},
#endif
...
...
@@ -428,10 +429,9 @@ static struct {
{
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_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_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
{
LOPT_PREF_CLSS
,
ARG_DUP
,
"set:tag,<class>"
,
gettext_noop
(
"Specify DHCPv6 prefix class"
),
NULL
},
#endif
...
...
@@ -3687,7 +3687,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
/* Upper bound on length */
new
->
key
=
opt_malloc
((
3
*
strlen
(
key64
)
/
4
));
new
->
key
=
opt_malloc
((
3
*
strlen
(
key64
)
/
4
)
+
1
);
unhide_metas
(
key64
);
if
((
new
->
keylen
=
parse_base64
(
key64
,
new
->
key
))
==
-
1
)
ret_err
(
_
(
"bad base64 in DNSKEY"
));
...
...
src/rfc1035.c
View file @
0975a58e
...
...
@@ -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
)
{
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 */
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
!
(
p
=
skip_section
(
p
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
+
ntohs
(
header
->
arcount
)
,
header
,
plen
)))
return
plen
;
*
p
++
=
0
;
/* empty name */
...
...
@@ -531,16 +534,16 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
rdlen
=
0
;
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
header
->
arcount
=
htons
(
1
);
header
->
arcount
=
htons
(
ntohs
(
header
->
arcount
)
+
1
);
datap
=
p
;
}
else
{
int
i
,
is_sign
;
int
i
;
unsigned
short
code
,
len
,
flags
;
/* Must be at the end, if exists */
if
(
ntohs
(
header
->
arcount
)
!=
1
||
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
))
||
is_sign
||
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
plen
;
...
...
@@ -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
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
char
*
p
=
(
unsigned
char
*
)(
header
+
1
);
...
...
@@ -1447,23 +1449,30 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
int
nameoffset
;
unsigned
short
flag
;
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
;
struct
crec
*
crecp
;
int
nxdomain
=
0
,
auth
=
1
,
trunc
=
0
,
sec_data
=
1
;
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
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
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
))
{
unsigned
short
udpsz
,
flags
;
unsigned
char
*
psave
=
pheader
;
have_pseudoheader
=
1
;
GETSHORT
(
udpsz
,
pheader
);
pheader
+=
2
;
/* ext_rcode */
GETSHORT
(
flags
,
pheader
);
...
...
@@ -1637,7 +1646,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
!
dryrun
)
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
;
if
(
!
(
crecp
->
flags
&
(
F_HOSTS
|
F_DHCP
)))
...
...
@@ -1834,7 +1843,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
!
dryrun
)
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,
filter here. */
...
...
@@ -2060,12 +2069,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if
(
trunc
)
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
)
SET_RCODE
(
header
,
NXDOMAIN
);
else
...
...
@@ -2073,6 +2076,18 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
header
->
ancount
=
htons
(
anscount
);
header
->
nscount
=
htons
(
0
);
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