automatic-interface-scan yes;\n\
bindkeys-file \"" NAMED_SYSCONFDIR "/bind.keys\";\n\
# blackhole {none;};\n"
-" cookie-algorithm aes;\n"
+" cookie-algorithm siphash24;\n"
#ifndef WIN32
" coresize default;\n\
datasize default;\n"
check-srv-cname ( fail | warn | ignore );
check-wildcard <replaceable>boolean</replaceable>;
clients-per-query <replaceable>integer</replaceable>;
- cookie-algorithm ( aes );
+ cookie-algorithm ( aes | siphash24 );
cookie-secret <replaceable>string</replaceable>;
coresize ( default | unlimited | <replaceable>sizeval</replaceable> );
datasize ( default | unlimited | <replaceable>sizeval</replaceable> );
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/resource.h>
+#include <isc/siphash.h>
#include <isc/socket.h>
#include <isc/stat.h>
#include <isc/stats.h>
obj = NULL;
result = named_config_get(maps, "cookie-algorithm", &obj);
INSIST(result == ISC_R_SUCCESS);
- if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
+ if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) {
+ server->sctx->cookiealg = ns_cookiealg_siphash24;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
server->sctx->cookiealg = ns_cookiealg_aes;
} else {
INSIST(0);
usedlength = isc_buffer_usedlength(&b);
switch (server->sctx->cookiealg) {
+ case ns_cookiealg_siphash24:
+ expectedlength = ISC_SIPHASH24_KEY_LENGTH;
+ if (usedlength != expectedlength) {
+ CHECKM(ISC_R_RANGE,
+ "SipHash-2-4 cookie-secret must be 128 bits");
+ }
+ break;
case ns_cookiealg_aes:
expectedlength = ISC_AES128_KEYLENGTH;
if (usedlength != expectedlength) {
CHECKM(ISC_R_RANGE,
- "AES cookie-secret must be "
- "128 bits");
+ "AES cookie-secret must be 128 bits");
}
break;
}
*/
options {
- cookie-algorithm sha1;
- cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 160 bits
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaa"; // 136 bits
};
*/
options {
- cookie-algorithm sha256;
- cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 160 bits
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaabbccdd"; // 160 bits
};
*/
options {
- cookie-algorithm sha1;
- cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272fff"; // 168 bits
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
};
*/
options {
- cookie-algorithm sha256;
- cookie-secret "b174e3800b6734f73268f15831c957860a8ee1229cfb9039c1514836f53efbed";
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
};
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
require-server-cookie yes;
};
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
- cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
require-server-cookie yes;
};
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ cookie-algorithm siphash24;
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
require-server-cookie yes;
};
#
# Test shared cookie-secret support.
#
-# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
#
-# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
-# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3"; (alternate)
+# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
+# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; (alternate)
#
-# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
#
# Server cookies from NS4 are accepted by NS5 and not NS6
# Server cookies from NS5 are accepted by NS4 and not NS6
docdir
oldincludedir
includedir
-runstatedir
localstatedir
sharedstatedir
sysconfdir
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
- -runstatedir | --runstatedir | --runstatedi | --runstated \
- | --runstate | --runstat | --runsta | --runst | --runs \
- | --run | --ru | --r)
- ac_prev=runstatedir ;;
- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
- | --run=* | --ru=* | --r=*)
- runstatedir=$ac_optarg ;;
-
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir runstatedir
+ libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
check-wildcard <boolean>;
cleaning-interval <integer>; // obsolete
clients-per-query <integer>;
- cookie-algorithm ( aes );
+ cookie-algorithm ( aes | siphash24 );
cookie-secret <string>; // may occur multiple times
coresize ( default | unlimited | <sizeval> );
datasize ( default | unlimited | <sizeval> );
#include <isc/print.h>
#include <isc/region.h>
#include <isc/result.h>
+#include <isc/siphash.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/symtab.h>
dns_name_t *name;
isc_buffer_t b;
uint32_t lifetime = 3600;
- const char *ccalg = "aes";
+ const char *ccalg = "siphash24";
/*
* { "name", scale, value }
if (strcasecmp(ccalg, "aes") == 0 &&
usedlength != ISC_AES128_KEYLENGTH) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "AES cookie-secret must be "
- "128 bits");
+ "AES cookie-secret must be 128 bits");
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_RANGE;
+ }
+ if (strcasecmp(ccalg, "siphash24") == 0 &&
+ usedlength != ISC_SIPHASH24_KEY_LENGTH) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "SipHash-2-4 cookie-secret must be 128 bits");
if (result == ISC_R_SUCCESS)
result = ISC_R_RANGE;
}
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
+#include <isc/siphash.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
-#include <isc/aes.h>
-
#include <dns/acl.h>
#include <dns/adb.h>
#include <dns/badcache.h>
isc_mem_t * mctx;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatch;
- bool exclusivesocket;
+ bool exclusivesocket;
dns_adbaddrinfo_t * addrinfo;
isc_socket_t * tcpsocket;
isc_time_t start;
dns_tsigkey_t *tsigkey;
isc_socketevent_t sendevent;
isc_dscp_t dscp;
- int ednsversion;
+ int ednsversion;
unsigned int options;
isc_sockeventattr_t attributes;
unsigned int sends;
ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
}
-static void
-compute_cc(resquery_t *query, unsigned char *cookie, size_t len) {
- unsigned char digest[ISC_AES_BLOCK_LENGTH];
- unsigned char input[16];
+static inline size_t
+addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) {
isc_netaddr_t netaddr;
- unsigned int i;
-
- INSIST(len >= 8U);
-
- isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
switch (netaddr.family) {
case AF_INET:
- memmove(input, (unsigned char *)&netaddr.type.in, 4);
- memset(input + 4, 0, 12);
- break;
+ INSIST(bufsize >= 4);
+ memmove(buf, &netaddr.type.in, 4);
+ return (4);
case AF_INET6:
- memmove(input, (unsigned char *)&netaddr.type.in6, 16);
- break;
+ INSIST(bufsize >= 16);
+ memmove(buf, &netaddr.type.in6, 16);
+ return (16);
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
}
- isc_aes128_crypt(query->fctx->res->view->secret, input, digest);
- for (i = 0; i < 8; i++)
- digest[i] ^= digest[i + 8];
- memmove(cookie, digest, 8);
+ return (0);
+}
+
+static inline isc_socket_t *
+query2sock(const resquery_t *query) {
+ if (query->exclusivesocket) {
+ return (dns_dispatch_getentrysocket(query->dispentry));
+ } else {
+ return (dns_dispatch_getsocket(query->dispatch));
+ }
+}
+
+static inline size_t
+add_serveraddr(uint8_t *buf, const size_t bufsize, const resquery_t *query)
+{
+ return (addr2buf(buf, bufsize, &query->addrinfo->sockaddr));
+}
+
+#define CLIENT_COOKIE_SIZE 8U
+
+static void
+compute_cc(const resquery_t *query, uint8_t *cookie, const size_t len) {
+ INSIST(len >= CLIENT_COOKIE_SIZE);
+ STATIC_ASSERT(sizeof(query->fctx->res->view->secret)
+ >= ISC_SIPHASH24_KEY_LENGTH,
+ "The view->secret size can't fit SipHash 2-4 key length");
+
+ uint8_t buf[16] ISC_NONSTRING = { 0 };
+ size_t buflen = add_serveraddr(buf, sizeof(buf), query);
+
+ uint8_t digest[ISC_SIPHASH24_TAG_LENGTH] ISC_NONSTRING = { 0 };
+ isc_siphash24(query->fctx->res->view->secret, buf, buflen, digest);
+ memmove(cookie, digest, CLIENT_COOKIE_SIZE);
}
static isc_result_t
*/
dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
- if (query->exclusivesocket)
- sock = dns_dispatch_getentrysocket(query->dispentry);
- else
- sock = dns_dispatch_getsocket(query->dispatch);
+ sock = query2sock(query);
+
/*
* Send the query!
*/
REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
valarg = event->ev_arg;
fctx = valarg->fctx;
+ REQUIRE(VALID_FCTX(fctx));
res = fctx->res;
addrinfo = valarg->addrinfo;
- REQUIRE(VALID_FCTX(fctx));
REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
vevent = (dns_validatorevent_t *)event;
dtmsgtype = DNS_DTTYPE_RR;
}
- if (rctx->query->exclusivesocket) {
- sock = dns_dispatch_getentrysocket(rctx->query->dispentry);
- } else {
- sock = dns_dispatch_getsocket(rctx->query->dispatch);
- }
+ sock = query2sock(rctx->query);
if (sock != NULL) {
result = isc_socket_getsockname(sock, &localaddr);
*/
#define UNUSED(x) (void)(x)
+#if __GNUC__ >= 8 && !defined(__clang__)
+#define ISC_NONSTRING __attribute__((nonstring))
+#else
+#define ISC_NONSTRING
+#endif /* __GNUC__ */
+
/*%
* The opposite: silent warnings about stored values which are never read.
*/
&cfg_rep_list, &cfg_type_portrange
};
-static const char *cookiealg_enums[] = { "aes", NULL };
+static const char *cookiealg_enums[] = { "aes", "siphash24", NULL };
static cfg_type_t cfg_type_cookiealg = {
"cookiealg", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &cookiealg_enums
#include <isc/random.h>
#include <isc/safe.h>
#include <isc/serial.h>
+#include <isc/siphash.h>
#include <isc/stats.h>
#include <isc/stdio.h>
#include <isc/string.h>
compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
const unsigned char *secret, isc_buffer_t *buf)
{
+ unsigned char digest[ISC_MAX_MD_SIZE] ISC_NONSTRING = { 0 };;
+ STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_SIPHASH24_TAG_LENGTH,
+ "You need to increase the digest buffer.");
+ STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_AES_BLOCK_LENGTH,
+ "You need to increase the digest buffer.");
+
switch (client->sctx->cookiealg) {
+ case ns_cookiealg_siphash24: {
+ unsigned char input[16 + 16] ISC_NONSTRING = { 0 };
+ size_t inputlen = 0;
+ isc_netaddr_t netaddr;
+ unsigned char *cp;
+
+ cp = isc_buffer_used(buf);
+ isc_buffer_putmem(buf, client->cookie, 8);
+ isc_buffer_putuint8(buf, NS_COOKIE_VERSION_1);
+ isc_buffer_putuint24(buf, 0); /* Reserved */
+ isc_buffer_putuint32(buf, when);
+
+ memmove(input, cp, 16);
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ cp = (unsigned char *)&netaddr.type.in;
+ memmove(input + 16, cp, 4);
+ inputlen = 20;
+ break;
+ case AF_INET6:
+ cp = (unsigned char *)&netaddr.type.in6;
+ memmove(input + 16, cp, 16);
+ inputlen = 32;
+ break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
+ }
+
+ isc_siphash24(secret, input, inputlen, digest);
+ isc_buffer_putmem(buf, digest, 8);
+ break;
+ }
case ns_cookiealg_aes: {
- unsigned char digest[ISC_AES_BLOCK_LENGTH];
- unsigned char input[4 + 4 + 16];
+ unsigned char input[4 + 4 + 16] ISC_NONSTRING = { 0 };
isc_netaddr_t netaddr;
unsigned char *cp;
unsigned int i;
- memset(input, 0, sizeof(input));
cp = isc_buffer_used(buf);
isc_buffer_putmem(buf, client->cookie, 8);
isc_buffer_putuint32(buf, nonce);
isc_buffer_putuint32(buf, when);
memmove(input, cp, 16);
isc_aes128_crypt(secret, input, digest);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
input[i] = digest[i] ^ digest[i + 8];
+ }
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
switch (netaddr.family) {
case AF_INET:
cp = (unsigned char *)&netaddr.type.in6;
memmove(input + 8, cp, 16);
isc_aes128_crypt(secret, input, digest);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
input[i + 8] = digest[i] ^ digest[i + 8];
+ }
isc_aes128_crypt(client->sctx->secret, input + 8,
digest);
break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
}
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
digest[i] ^= digest[i + 8];
+ }
isc_buffer_putmem(buf, digest, 8);
break;
}
typedef struct ns_stats ns_stats_t;
typedef enum {
- ns_cookiealg_aes
+ ns_cookiealg_aes,
+ ns_cookiealg_siphash24
} ns_cookiealg_t;
+#define NS_COOKIE_VERSION_1 1
+
#endif /* NS_TYPES_H */