From: Mark Andrews Date: Wed, 19 Feb 2014 01:53:42 +0000 (+1100) Subject: 3744. [experimental] SIT: send and process Source Identity Tokens X-Git-Tag: v9.10.0b1~83 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=b5f6271f4daf1e54501af2cb7dd278d7e8003d65;p=thirdparty%2Fbind9.git 3744. [experimental] SIT: send and process Source Identity Tokens (which are similar to DNS Cookies by Donald Eastlake) and are designed to help clients detect off path spoofed responses and for servers to detect legitimate clients. SIT use a experimental EDNS option code (65001). SIT can be enabled via --enable-developer or --enable-sit. It is on by default in Windows. RRL processing as been updated to know about SIT with legitimate clients not being rate limited. [RT #35389] --- diff --git a/CHANGES b/CHANGES index b5de78372f1..e70a3284ed7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,17 @@ +3744. [experimental] SIT: send and process Source Identity Tokens + (which are similar to DNS Cookies by Donald Eastlake) + and are designed to help clients detect off path + spoofed responses and for servers to detect legitimate + clients. + + SIT use a experimental EDNS option code (65001). + + SIT can be enabled via --enable-developer or + --enable-sit. It is on by default in Windows. + + RRL processing as been updated to know about SIT with + legitimate clients not being rate limited. [RT #35389] + 3743. [bug] delegation-only flag wasn't working in forward zone declarations despite being documented. This is needed to support turning off forwarding and turning diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 2d47579d04a..d0d3ed01d6d 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -63,6 +63,9 @@ static char *argv0; static int addresscount = 0; static char domainopt[DNS_NAME_MAXTEXT]; +#ifdef ISC_PLATFORM_USESIT +static char sitvalue[256]; +#endif static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, @@ -223,6 +226,9 @@ help(void) { " +[no]trace (Trace delegation down from root [+dnssec])\n" " +[no]dnssec (Request DNSSEC records)\n" " +[no]nsid (Request Name Server ID)\n" +#ifdef ISC_PLATFORM_USESIT +" +[no]sit (Request a Source Identity Token)\n" +#endif #ifdef DIG_SIGCHASE " +[no]sigchase (Chase DNSSEC signatures)\n" " +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n" @@ -1086,14 +1092,34 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto invalid_option; } break; + case 'i': + switch (cmd[2]) { #ifdef DIG_SIGCHASE - case 'i': /* sigchase */ - FULLCHECK("sigchase"); - lookup->sigchase = state; - if (lookup->sigchase) - lookup->dnssec = ISC_TRUE; - break; + case 'g': /* sigchase */ + FULLCHECK("sigchase"); + lookup->sigchase = state; + if (lookup->sigchase) + lookup->dnssec = ISC_TRUE; + break; #endif +#ifdef ISC_PLATFORM_USESIT + case 't': /* sit */ + FULLCHECK("sit"); + if (state && lookup->edns == -1) + lookup->edns = 0; + lookup->sit = state; + if (value != NULL) { + strncpy(sitvalue, value, + sizeof(sitvalue)); + lookup->sitvalue = sitvalue; + } else + lookup->sitvalue = NULL; + break; +#endif + default: + goto invalid_option; + } + break; case 'p': /* split */ FULLCHECK("split"); if (value != NULL && !state) diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index d2c04394a5a..2db8a5b9f27 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -924,6 +924,18 @@ + + + + + Send a Source Identity Token EDNS option, with optional value. + Replaying a SIT from a previous response will allow the + server to identify a previous client. The default is + . + + + + diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 94ab2971665..baef5f7d18d 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,8 @@ int fatalexit = 0; char keynametext[MXNAME]; char keyfile[MXNAME] = ""; char keysecret[MXNAME] = ""; +unsigned char cookie_secret[33]; +unsigned char cookie[8]; dns_name_t *hmacname = NULL; unsigned int digestbits = 0; isc_buffer_t *namebuf = NULL; @@ -766,6 +769,9 @@ make_empty_lookup(void) { looknew->besteffort = ISC_TRUE; looknew->dnssec = ISC_FALSE; looknew->nsid = ISC_FALSE; +#ifdef ISC_PLATFORM_USESIT + looknew->sit = ISC_FALSE; +#endif #ifdef DIG_SIGCHASE looknew->sigchase = ISC_FALSE; #if DIG_SIGCHASE_TD @@ -801,6 +807,9 @@ make_empty_lookup(void) { looknew->new_search = ISC_FALSE; looknew->done_as_is = ISC_FALSE; looknew->need_search = ISC_FALSE; +#ifdef ISC_PLATFORM_USESIT + looknew->sitvalue = NULL; +#endif ISC_LINK_INIT(looknew, link); ISC_LIST_INIT(looknew->q); ISC_LIST_INIT(looknew->connecting); @@ -847,6 +856,10 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { looknew->besteffort = lookold->besteffort; looknew->dnssec = lookold->dnssec; looknew->nsid = lookold->nsid; +#ifdef ISC_PLATFORM_USESIT + looknew->sit = lookold->sit; + looknew->sitvalue = lookold->sitvalue; +#endif #ifdef DIG_SIGCHASE looknew->sigchase = lookold->sigchase; #if DIG_SIGCHASE_TD @@ -1210,6 +1223,7 @@ setup_system(void) { dig_searchlist_t *domain = NULL; lwres_result_t lwresult; unsigned int lwresflags; + isc_result_t result; debug("setup_system()"); @@ -1288,7 +1302,10 @@ setup_system(void) { #endif #endif - + result = isc_entropy_getdata(entp, cookie_secret, + sizeof(cookie_secret), NULL, 0); + if (result != ISC_R_SUCCESS) + fatal("unable to generate cookie secret"); } /*% @@ -1381,46 +1398,18 @@ setup_libs(void) { */ static void add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, - isc_boolean_t dnssec, isc_boolean_t nsid) + isc_boolean_t dnssec, dns_ednsopt_t *ednsopts, size_t count) { dns_rdataset_t *rdataset = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdata_t *rdata = NULL; isc_result_t result; + unsigned int flags = 0; debug("add_opt()"); - result = dns_message_gettemprdataset(msg, &rdataset); - check_result(result, "dns_message_gettemprdataset"); - dns_rdataset_init(rdataset); - result = dns_message_gettemprdatalist(msg, &rdatalist); - check_result(result, "dns_message_gettemprdatalist"); - result = dns_message_gettemprdata(msg, &rdata); - check_result(result, "dns_message_gettemprdata"); - - debug("setting udp size of %d", udpsize); - rdatalist->type = dns_rdatatype_opt; - rdatalist->covers = 0; - rdatalist->rdclass = udpsize; - rdatalist->ttl = edns << 16; if (dnssec) - rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO; - if (nsid) { - isc_buffer_t *b = NULL; - - result = isc_buffer_allocate(mctx, &b, 4); - check_result(result, "isc_buffer_allocate"); - isc_buffer_putuint16(b, DNS_OPT_NSID); - isc_buffer_putuint16(b, 0); - rdata->data = isc_buffer_base(b); - rdata->length = isc_buffer_usedlength(b); - dns_message_takebuffer(msg, &b); - } else { - rdata->data = NULL; - rdata->length = 0; - } - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - dns_rdatalist_tordataset(rdatalist, rdataset); + flags |= DNS_MESSAGEEXTFLAG_DO; + result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags, + ednsopts, count); + check_result(result, "dns_message_buildopt"); result = dns_message_setopt(msg, rdataset); check_result(result, "dns_message_setopt"); } @@ -2008,6 +1997,15 @@ insert_soa(dig_lookup_t *lookup) { dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); } +#ifdef ISC_PLATFORM_USESIT +static void +compute_cookie(unsigned char *cookie, size_t len) { + /* XXXMPA need to fix, should be per server. */ + INSIST(len >= 8U); + memcpy(cookie, cookie_secret, 8); +} +#endif + /*% * Setup the supplied lookup structure, making it ready to start sending * queries to servers. Create and initialize the message to be sent as @@ -2276,12 +2274,44 @@ setup_lookup(dig_lookup_t *lookup) { &lookup->renderbuf); check_result(result, "dns_message_renderbegin"); if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) { +#define EDNSOPTS 2 + dns_ednsopt_t opts[EDNSOPTS]; + int i = 0; if (lookup->udpsize == 0) lookup->udpsize = 4096; if (lookup->edns < 0) lookup->edns = 0; + if (lookup->nsid) { + INSIST(i < EDNSOPTS); + opts[i].code = DNS_OPT_NSID; + opts[i].length = 0; + opts[i].value = NULL; + i++; + } +#ifdef ISC_PLATFORM_USESIT + if (lookup->sit) { + INSIST(i < EDNSOPTS); + opts[i].code = DNS_OPT_SIT; + if (lookup->sitvalue != NULL) { + char bb[256]; + isc_buffer_t b; + + isc_buffer_init(&b, bb, sizeof(bb)); + result = isc_hex_decodestring(lookup->sitvalue, + &b); + check_result(result, "isc_hex_decodestring"); + opts[i].value = isc_buffer_base(&b); + opts[i].length = isc_buffer_usedlength(&b); + } else { + compute_cookie(cookie, sizeof(cookie)); + opts[i].length = 8; + opts[i].value = cookie; + } + i++; + } +#endif add_opt(lookup->sendmsg, lookup->udpsize, - lookup->edns, lookup->dnssec, lookup->nsid); + lookup->edns, lookup->dnssec, opts, i); } result = dns_message_rendersection(lookup->sendmsg, @@ -3109,6 +3139,67 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg, return (ISC_TRUE); } +#ifdef ISC_PLATFORM_USESIT +static void +process_sit(dig_lookup_t *l, isc_buffer_t *optbuf, size_t optlen) { + char bb[256]; + isc_buffer_t hexbuf; + size_t len; + const unsigned char *sit; + isc_result_t result; + + if (l->sitvalue != NULL) { + isc_buffer_init(&hexbuf, bb, sizeof(bb)); + result = isc_hex_decodestring(l->sitvalue, &hexbuf); + check_result(result, "isc_hex_decodestring"); + sit = isc_buffer_base(&hexbuf); + len = isc_buffer_usedlength(&hexbuf); + } else { + sit = cookie; + len = sizeof(cookie); + } + + if (optlen >= len && optlen >= 8U) { + if (memcmp(isc_buffer_current(optbuf), sit, 8) == 0) { + if (l->comments) + printf(";; SIT client cookie part match\n"); + } else + printf(";; Warning: SIT client cookie part mis-match\n"); + } else + printf(";; Warning: SIT bad token (too short)\n"); + isc_buffer_forward(optbuf, optlen); +} + +static void +process_opt(dig_lookup_t *l, dns_rdataset_t *opt) { + dns_rdata_t rdata; + isc_result_t result; + isc_buffer_t optbuf; + isc_uint16_t optcode, optlen; + + result = dns_rdataset_first(opt); + if (result == ISC_R_SUCCESS) { + dns_rdata_init(&rdata); + dns_rdataset_current(opt, &rdata); + isc_buffer_init(&optbuf, rdata.data, rdata.length); + isc_buffer_add(&optbuf, rdata.length); + while (isc_buffer_remaininglength(&optbuf) >= 4) { + optcode = isc_buffer_getuint16(&optbuf); + optlen = isc_buffer_getuint16(&optbuf); + switch (optcode) { + case DNS_OPT_SIT: + process_sit(l, &optbuf, optlen); + break; + default: + isc_buffer_forward(&optbuf, optlen); + break; + } + } + } +} +#endif + + /*% * Event handler for recv complete. Perform whatever actions are necessary, * based on the specifics of the user's request. @@ -3369,7 +3460,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { } if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore && !l->tcp_mode) { - printf(";; Truncated, retrying in TCP mode.\n"); + if (l->comments) + printf(";; Truncated, retrying in TCP mode.\n"); n = requeue_lookup(l, ISC_TRUE); n->tcp_mode = ISC_TRUE; n->origin = query->lookup->origin; @@ -3401,7 +3493,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { */ if ((ISC_LIST_HEAD(l->q) != query) || (ISC_LIST_NEXT(query, link) != NULL)) { - if( l->comments == ISC_TRUE ) + if (l->comments) printf(";; Got %s from %s, " "trying next server\n", msg->rcode == dns_rcode_servfail ? @@ -3469,6 +3561,16 @@ recv_done(isc_task_t *task, isc_event_t *event) { } } +#ifdef ISC_PLATFORM_USESIT + if (l->sitvalue != NULL) { + if (msg->opt == NULL) + printf(";; expected opt record in response\n"); + else + process_opt(l, msg->opt); + } else if (l->sit && msg->opt != NULL) + process_opt(l, msg->opt); +#endif + if (!l->doing_xfr || l->xfr_q == query) { if (msg->rcode == dns_rcode_nxdomain && (l->origin != NULL || l->need_search)) { diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 0150d11dfb3..83cd24d2ecf 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -130,6 +130,9 @@ struct dig_lookup { done_as_is, besteffort, dnssec, +#ifdef ISC_PLATFORM_USESIT + sit, +#endif nsid; /*% Name Server ID (RFC 5001) */ #ifdef DIG_SIGCHASE isc_boolean_t sigchase; @@ -184,6 +187,9 @@ isc_boolean_t sigchase; isc_buffer_t *querysig; isc_uint32_t msgcounter; dns_fixedname_t fdomain; +#ifdef ISC_PLATFORM_USESIT + char *sitvalue; +#endif }; /*% The dig_query structure */ diff --git a/bin/named/client.c b/bin/named/client.c index 1597ebdb4ed..f16f4045d47 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,6 +34,12 @@ #include #include +#ifdef AES_SIT +#include +#else +#include +#endif + #include #include #include @@ -113,6 +121,9 @@ */ #endif +#define SIT_SIZE 24 /* 8 + 4 + 4 + 8 */ +#define EDNSOPTS 2 + /*% nameserver client manager structure */ struct ns_clientmgr { /* Unlocked. */ @@ -235,6 +246,10 @@ static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, dns_dispatch_t *disp, isc_boolean_t tcp); static inline isc_boolean_t allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl); +#ifdef ISC_PLATFORM_USESIT +static void compute_sit(ns_client_t *client, isc_uint32_t when, + isc_uint32_t nonce, isc_buffer_t *buf); +#endif void ns_client_recursing(ns_client_t *client) { @@ -802,10 +817,24 @@ client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer, } } else { data = sendbuf; +#ifdef ISC_PLATFORM_USESIT + if ((client->attributes & NS_CLIENTATTR_HAVESIT) == 0) { + if (client->view != NULL) + bufsize = client->view->situdp; + else + bufsize = 512; + } else + bufsize = client->udpsize; + if (bufsize > client->udpsize) + bufsize = client->udpsize; + if (bufsize > SEND_BUFFER_SIZE) + bufsize = SEND_BUFFER_SIZE; +#else if (client->udpsize < SEND_BUFFER_SIZE) bufsize = client->udpsize; else bufsize = SEND_BUFFER_SIZE; +#endif if (length > bufsize) { result = ISC_R_NOSPACE; goto done; @@ -1342,11 +1371,14 @@ ns_client_error(ns_client_t *client, isc_result_t result) { static inline isc_result_t client_addopt(ns_client_t *client) { char nsid[BUFSIZ], *nsidp; +#ifdef ISC_PLATFORM_USESIT + unsigned char sit[SIT_SIZE]; +#endif isc_result_t result; dns_view_t *view; dns_resolver_t *resolver; isc_uint16_t udpsize; - dns_ednsopt_t ednsopts[2]; + dns_ednsopt_t ednsopts[EDNSOPTS]; int count = 0; unsigned int flags; @@ -1375,12 +1407,33 @@ client_addopt(ns_client_t *client) { } else nsidp = ns_g_server->server_id; + INSIST(count < EDNSOPTS); ednsopts[count].code = DNS_OPT_NSID; ednsopts[count].length = strlen(nsidp); ednsopts[count].value = (unsigned char *)nsidp; count++; } no_nsid: +#ifdef ISC_PLATFORM_USESIT + if ((client->attributes & NS_CLIENTATTR_WANTSIT) != 0) { + isc_buffer_t buf; + isc_stdtime_t now; + isc_uint32_t nonce; + + isc_buffer_init(&buf, sit, sizeof(sit)); + isc_stdtime_get(&now); + isc_random_get(&nonce); + + compute_sit(client, now, nonce, &buf); + + INSIST(count < EDNSOPTS); + ednsopts[count].code = DNS_OPT_SIT; + ednsopts[count].length = SIT_SIZE; + ednsopts[count].value = sit; + count++; + } +#endif + result = dns_message_buildopt(client->message, &client->opt, 0, udpsize, flags, ednsopts, count); return (result); @@ -1464,6 +1517,179 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, return (ISC_TF(view == myview)); } +#ifdef ISC_PLATFORM_USESIT +static void +compute_sit(ns_client_t *client, isc_uint32_t when, isc_uint32_t nonce, + isc_buffer_t *buf) +{ +#ifdef AES_SIT + unsigned char digest[ISC_AES_BLOCK_LENGTH]; + unsigned char input[4 + 4 + 16]; + isc_netaddr_t netaddr; + unsigned char *cp; + unsigned int i; + + cp = isc_buffer_used(buf); + isc_buffer_putmem(buf, client->cookie, 8); + isc_buffer_putuint32(buf, nonce); + isc_buffer_putuint32(buf, when); + memcpy(input, cp, 8); + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + switch (netaddr.family) { + case AF_INET: + memcpy(input + 8, (unsigned char *)&netaddr.type.in, 4); + memset(input + 12, 0, 4); + isc_aes128_crypt(ns_g_server->secret, input, digest); + break; + case AF_INET6: + memcpy(input + 8, (unsigned char *)&netaddr.type.in6, 16); + isc_aes128_crypt(ns_g_server->secret, input, digest); + for (i = 0; i < 8; i++) + input[i + 8] = digest[i] ^ digest[i + 8]; + isc_aes128_crypt(ns_g_server->secret, input + 8, digest); + break; + } + memcpy(input, client->cookie, 8); + for (i = 0; i < 8; i++) + input[i + 8] = digest[i] ^ digest[i + 8]; + isc_aes128_crypt(ns_g_server->secret, input, digest); + for (i = 0; i < 8; i++) + digest[i] ^= digest[i + 8]; + isc_buffer_putmem(buf, digest, 8); +#endif +#ifdef HMAC_SHA1_SIT + unsigned char digest[ISC_SHA1_DIGESTLENGTH]; + isc_netaddr_t netaddr; + unsigned char *cp; + isc_hmacsha1_t hmacsha1; + + cp = isc_buffer_used(buf); + isc_buffer_putuint32(buf, nonce); + isc_buffer_putuint32(buf, when); + + isc_hmacsha1_init(&hmacsha1, + ns_g_server->secret, + ISC_SHA1_DIGESTLENGTH); + isc_hmacsha1_update(&hmacsha1, cp, 8); + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + switch (netaddr.family) { + case AF_INET: + isc_hmacsha1_update(&hmacsha1, + (unsigned char *)&netaddr.type.in, 4); + break; + case AF_INET6: + isc_hmacsha1_update(&hmacsha1, + (unsigned char *)&netaddr.type.in6, 16); + break; + } + isc_hmacsha1_update(&hmacsha1, client->cookie, sizeof(client->cookie)); + isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest)); + isc_buffer_putmem(buf, digest, 8); + isc_hmacsha1_invalidate(&hmacsha1); +#endif +#ifdef HMAC_SHA256_SIT + unsigned char digest[ISC_SHA256_DIGESTLENGTH]; + isc_netaddr_t netaddr; + unsigned char *cp; + isc_hmacsha256_t hmacsha256; + + cp = isc_buffer_used(buf); + isc_buffer_putuint32(buf, nonce); + isc_buffer_putuint32(buf, when); + + isc_hmacsha256_init(&hmacsha256, + ns_g_server->secret, + ISC_SHA256_DIGESTLENGTH); + isc_hmacsha256_update(&hmacsha256, cp, 8); + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + switch (netaddr.family) { + case AF_INET: + isc_hmacsha256_update(&hmacsha256, + (unsigned char *)&netaddr.type.in, 4); + break; + case AF_INET6: + isc_hmacsha256_update(&hmacsha256, + (unsigned char *)&netaddr.type.in6, 16); + break; + } + isc_hmacsha256_update(&hmacsha256, client->cookie, + sizeof(client->cookie)); + isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest)); + isc_buffer_putmem(buf, digest, 8); + isc_hmacsha256_invalidate(&hmacsha256); +#endif +} + +static void +process_sit(ns_client_t *client, isc_buffer_t *buf, size_t optlen) { + unsigned char dbuf[SIT_SIZE]; + unsigned char *old; + isc_stdtime_t now; + isc_uint32_t when; + isc_uint32_t nonce; + isc_buffer_t db; + + client->attributes |= NS_CLIENTATTR_WANTSIT; + + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitopt); + + if (optlen != SIT_SIZE) { + /* + * Not our token. + */ + if (optlen >= 8U) + memcpy(client->cookie, isc_buffer_current(buf), 8); + else + memset(client->cookie, 0, 8); + isc_buffer_forward(buf, optlen); + + if (optlen == 8) + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitnew); + else + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitbadsize); + return; + } + + /* + * Process all of the incoming buffer. + */ + old = isc_buffer_current(buf); + memcpy(client->cookie, old, 8); + isc_buffer_forward(buf, 8); + nonce = isc_buffer_getuint32(buf); + when = isc_buffer_getuint32(buf); + isc_buffer_forward(buf, 8); + + /* + * Allow for a 5 minute clock skew between servers sharing a secret. + * Only accept SIT if we have talked to the client in the last hour. + */ + isc_stdtime_get(&now); + if (isc_serial_gt(when, (now + 300)) || /* In the future. */ + isc_serial_lt(when, (now - 3600))) { /* In the past. */ + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitbadtime); + return; + } + + isc_buffer_init(&db, dbuf, sizeof(dbuf)); + compute_sit(client, when, nonce, &db); + + if (memcmp(old, dbuf, SIT_SIZE) != 0) { + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitnomatch); + return; + } + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_sitmatch); + + client->attributes |= NS_CLIENTATTR_HAVESIT; +} +#endif + static isc_result_t process_opt(ns_client_t *client, dns_rdataset_t *opt) { dns_rdata_t rdata; @@ -1520,6 +1746,11 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { client->attributes |= NS_CLIENTATTR_WANTNSID; isc_buffer_forward(&optbuf, optlen); break; +#ifdef ISC_PLATFORM_USESIT + case DNS_OPT_SIT: + process_sit(client, &optbuf, optlen); + break; +#endif default: isc_buffer_forward(&optbuf, optlen); break; diff --git a/bin/named/config.c b/bin/named/config.c index 22d31bed696..55155726a37 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -112,6 +112,14 @@ options {\n\ use-ixfr true;\n\ edns-udp-size 4096;\n\ max-udp-size 4096;\n\ +" +#ifdef ISC_PLATFORM_USESIT +"\ + nosit-udp-size 4096;\n\ + request-sit true;\n\ +" +#endif +"\ request-nsid false;\n\ reserved-sockets 512;\n\ \n\ diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index a1387c65577..870877fa2fe 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -161,6 +161,7 @@ struct ns_client { ISC_LINK(ns_client_t) link; ISC_LINK(ns_client_t) rlink; ISC_QLINK(ns_client_t) ilink; + unsigned char cookie[8]; }; typedef ISC_QUEUE(ns_client_t) client_queue_t; @@ -180,6 +181,8 @@ typedef ISC_LIST(ns_client_t) client_list_t; #define NS_CLIENTATTR_FILTER_AAAA_RC 0x080 /*%< recursing for A against AAAA */ #endif #define NS_CLIENTATTR_WANTAD 0x100 /*%< want AD in response if possible */ +#define NS_CLIENTATTR_WANTSIT 0x200 /*%< include SIT */ +#define NS_CLIENTATTR_HAVESIT 0x400 /*%< has a valid SIT */ extern unsigned int ns_client_requests; diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 6c968fcdc23..246f516c75e 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -116,6 +116,7 @@ struct ns_server { unsigned int session_keyalg; isc_uint16_t session_keybits; isc_boolean_t interface_auto; + unsigned char secret[33]; /*%< Source Identity Token */ }; #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') @@ -179,7 +180,18 @@ enum { dns_nsstatscounter_udp = 41, dns_nsstatscounter_tcp = 42, +#ifdef ISC_PLATFORM_USESIT + dns_nsstatscounter_sitopt = 43, + dns_nsstatscounter_sitbadsize = 44, + dns_nsstatscounter_sitbadtime = 45, + dns_nsstatscounter_sitnomatch = 46, + dns_nsstatscounter_sitmatch = 47, + dns_nsstatscounter_sitnew = 48, + + dns_nsstatscounter_max = 49 +#else dns_nsstatscounter_max = 43 +#endif }; void diff --git a/bin/named/query.c b/bin/named/query.c index ce4bce34fdf..2ffd7dec980 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -98,6 +98,13 @@ /*% Want WANTAD? */ #define WANTAD(c) (((c)->attributes & \ NS_CLIENTATTR_WANTAD) != 0) +#ifdef ISC_PLATFORM_USESIT +/*% Client presented a valid Source Identity Token. */ +#define HAVESIT(c) (((c)->attributes & \ + NS_CLIENTATTR_HAVESIT) != 0) +#else +#define HAVESIT(c) (0) +#endif /*% No authority? */ #define NOAUTHORITY(c) (((c)->query.attributes & \ @@ -6371,7 +6378,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * Don't mess with responses rewritten by RPZ * Count each response at most once. */ - if (client->view->rrl != NULL && + if (client->view->rrl != NULL && !HAVESIT(client) && ((fname != NULL && dns_name_isabsolute(fname)) || (result == ISC_R_NOTFOUND && !RECURSIONOK(client))) && !(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) && diff --git a/bin/named/server.c b/bin/named/server.c index ad5449c8211..675e200f2c1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,12 @@ #include #include +#ifdef AES_SIT +#include +#else +#include +#endif + #include #include @@ -1157,6 +1164,13 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { if (obj != NULL) CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); +#ifdef ISC_PLATFORM_USESIT + obj = NULL; + (void)cfg_map_get(cpeer, "request-sit", &obj); + if (obj != NULL) + CHECK(dns_peer_setrequestsit(peer, cfg_obj_asboolean(obj))); +#endif + obj = NULL; (void)cfg_map_get(cpeer, "edns", &obj); if (obj != NULL) @@ -2999,6 +3013,21 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, udpsize = 4096; view->maxudp = udpsize; +#ifdef ISC_PLATFORM_USESIT + /* + * Set the maximum UDP when a SIT is not provided. + */ + obj = NULL; + result = ns_config_get(maps, "nosit-udp-size", &obj); + INSIST(result == ISC_R_SUCCESS); + udpsize = cfg_obj_asuint32(obj); + if (udpsize < 128) + udpsize = 128; + if (udpsize > view->maxudp) + udpsize = view->maxudp; + view->situdp = udpsize; +#endif + /* * Set the maximum rsa exponent bits. */ @@ -3371,6 +3400,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, INSIST(result == ISC_R_SUCCESS); view->requestnsid = cfg_obj_asboolean(obj); +#ifdef ENABLE_LTR + obj = NULL; + result = ns_config_get(maps, "request-sit", &obj); + INSIST(result == ISC_R_SUCCESS); + view->requestsit = cfg_obj_asboolean(obj); +#endif + obj = NULL; result = ns_config_get(maps, "max-clients-per-query", &obj); INSIST(result == ISC_R_SUCCESS); @@ -4043,6 +4079,13 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, if (result != ISC_R_SUCCESS) return (result); + result = isc_entropy_getdata(ns_g_entropy, view->secret, + sizeof(view->secret), NULL, 0); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + #ifdef HAVE_GEOIP view->aclenv.geoip = ns_g_geoip; #endif @@ -6153,6 +6196,43 @@ load_configuration(const char *filename, ns_server_t *server, server->flushonshutdown = ISC_FALSE; } +#ifdef ENABLE_LTR + obj = NULL; + result = ns_config_get(maps, "sit-secret", &obj); + if (result == ISC_R_SUCCESS) { + isc_buffer_t b; + + memset(server->secret, 0, sizeof(server->secret)); + isc_buffer_init(&b, server->secret, sizeof(server->secret)); + result = isc_hex_decodestring(cfg_obj_asstring(obj), &b); + if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) + goto cleanup; +#ifdef AES_SIT + if (isc_buffer_usedlength(&b) != ISC_AES128_KEYLENGTH) + CHECKM(ISC_R_RANGE, + "AES sit-secret must be on 128 bits"); +#endif +#ifdef HMAC_SHA1_SIT + if (isc_buffer_usedlength(&b) != ISC_SHA1_DIGESTLENGTH) + CHECKM(ISC_R_RANGE, + "SHA1 sit-secret must be on 160 bits"); +#endif +#ifdef HMAC_SHA256_SIT + if (isc_buffer_usedlength(&b) != ISC_SHA256_DIGESTLENGTH) + CHECKM(ISC_R_RANGE, + "SHA256 sit-secret must be on 160 bits"); +#endif + } else { + result = isc_entropy_getdata(ns_g_entropy, + server->secret, + sizeof(server->secret), + NULL, + 0); + if (result != ISC_R_SUCCESS) + goto cleanup; + } +#endif + result = ISC_R_SUCCESS; cleanup: diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 04c7282d141..056391768e6 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -220,6 +220,19 @@ init_desc(void) { "RPZRewrites"); SET_NSSTATDESC(udp, "UDP queries received", "QryUDP"); SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP"); +#ifdef ISC_PLATFORM_USESIT + SET_NSSTATDESC(sitopt, "source identity token option received", + "SitOpt"); + SET_NSSTATDESC(sitnew, "new source identity token requested", + "SitNew"); + SET_NSSTATDESC(sitbadsize, "source identity token - bad size", + "SitBadSize"); + SET_NSSTATDESC(sitbadtime, "source identity token - bad time", + "SitBadTime"); + SET_NSSTATDESC(sitnomatch, "source identity token - no match", + "SitNoMatch"); + SET_NSSTATDESC(sitmatch, "source identity token - match", "SitMatch"); +#endif INSIST(i == dns_nsstatscounter_max); /* Initialize resolver statistics */ @@ -295,6 +308,15 @@ init_desc(void) { SET_RESSTATDESC(nfetch, "active fetches", "NumFetch"); SET_RESSTATDESC(buckets, "bucket size", "BucketSize"); SET_RESSTATDESC(refused, "REFUSED received", "REFUSED"); +#ifdef ISC_PLATFORM_USESIT + SET_RESSTATDESC(sitcc, "SIT sent client cookie only", + "SitClientOut"); + SET_RESSTATDESC(sitout, "SIT sent with client and server cookie", + "SitOut"); + SET_RESSTATDESC(sitin, "SIT replies received", "SitIn"); + SET_RESSTATDESC(sitok, "SIT client cookie ok", "SitClientOk"); +#endif + INSIST(i == dns_resstatscounter_max); /* Initialize adb statistics */ diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 80141341d5c..559fcbb13a8 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -70,7 +70,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin forward glue gost ixfr inline limits logfileconfig lwresd masterfile masterformat metadata notify nsupdate pending @PKCS11_TEST@ redirect resolver rndc rpz rrl rrchecker - rrsetorder rsabigexponent smartsign sortlist spf staticstub + rrsetorder rsabigexponent sit smartsign sortlist spf staticstub statistics stub tkey tsig tsiggss unknown upforwd verify views wildcard xfer xferquota zero zonechecks" diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 81d2b2b88c7..b68dcb40b18 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -2081,7 +2081,7 @@ echo server 10.53.0.3 5300 echo update add fail.nosign.example 300 in txt "reject me" echo send ) | $NSUPDATE > /dev/null 2>&1 && ret=1 -$DIG +noall +answer +dnssec -p 5300 fail.nosign.example txt @10.53.0.3 \ +$DIG +tcp +noall +answer +dnssec -p 5300 fail.nosign.example txt @10.53.0.3 \ > dig.out.ns3.test$n 2>&1 [ -s dig.out.ns3.test$n ] && ret=1 n=`expr $n + 1` diff --git a/bin/tests/system/sit/.gitignore b/bin/tests/system/sit/.gitignore new file mode 100644 index 00000000000..eee491d3c6b --- /dev/null +++ b/bin/tests/system/sit/.gitignore @@ -0,0 +1 @@ +prereq.sh diff --git a/bin/tests/system/sit/clean.sh b/bin/tests/system/sit/clean.sh new file mode 100644 index 00000000000..8f80f3d934f --- /dev/null +++ b/bin/tests/system/sit/clean.sh @@ -0,0 +1,2 @@ +rm -f dig.out.* +rm -f ns1/named_dump.db diff --git a/bin/tests/system/sit/ns1/example.db b/bin/tests/system/sit/ns1/example.db new file mode 100644 index 00000000000..4619d8c4da5 --- /dev/null +++ b/bin/tests/system/sit/ns1/example.db @@ -0,0 +1,13 @@ +@ SOA ns1 hostmaster.isc.org. 1 600 600 1200 600 +@ NS ns1 +ns1 A 10.53.0.1 +large TXT ( large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large ) diff --git a/bin/tests/system/sit/ns1/named.conf b/bin/tests/system/sit/ns1/named.conf new file mode 100644 index 00000000000..e43e24fdb06 --- /dev/null +++ b/bin/tests/system/sit/ns1/named.conf @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1 dscp 1; + notify-source 10.53.0.1 dscp 2; + transfer-source 10.53.0.1 dscp 3; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + acache-enable yes; + deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } + except-from { "example.org"; }; + deny-answer-aliases { "example.org"; } + except-from { "goodcname.example.net"; + "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; + sit-secret "9be998f9e2f1550e549fbec072727dc6"; + request-sit yes; + nosit-udp-size 512; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "example" { + type master; + file "example.db"; +}; diff --git a/bin/tests/system/sit/ns1/root.hint b/bin/tests/system/sit/ns1/root.hint new file mode 100644 index 00000000000..2fd180e3ba7 --- /dev/null +++ b/bin/tests/system/sit/ns1/root.hint @@ -0,0 +1,20 @@ +; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +; Copyright (C) 2000, 2001 Internet Software Consortium. +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: root.hint,v 1.7 2007/06/19 23:47:05 tbox Exp $ + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/sit/ns2/named.conf b/bin/tests/system/sit/ns2/named.conf new file mode 100644 index 00000000000..04da91b2774 --- /dev/null +++ b/bin/tests/system/sit/ns2/named.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2 dscp 1; + notify-source 10.53.0.2 dscp 2; + transfer-source 10.53.0.2 dscp 3; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + acache-enable yes; + request-sit yes; + nosit-udp-size 512; +}; + +zone "." { + type master; + file "root.db"; +}; diff --git a/bin/tests/system/sit/ns2/root.db b/bin/tests/system/sit/ns2/root.db new file mode 100644 index 00000000000..49f3718a76a --- /dev/null +++ b/bin/tests/system/sit/ns2/root.db @@ -0,0 +1,13 @@ +@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.2 +large.xxx TXT ( large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large ) diff --git a/bin/tests/system/sit/prereq.sh.in b/bin/tests/system/sit/prereq.sh.in new file mode 100644 index 00000000000..da92848bf2e --- /dev/null +++ b/bin/tests/system/sit/prereq.sh.in @@ -0,0 +1,2 @@ +test "@HAVE_SIT@" = "" && exit 255 +exit 0 diff --git a/bin/tests/system/sit/tests.sh b/bin/tests/system/sit/tests.sh new file mode 100755 index 00000000000..8173d704cfc --- /dev/null +++ b/bin/tests/system/sit/tests.sh @@ -0,0 +1,92 @@ +#!/bin/sh +# +# Copyright (C) 2004, 2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2000, 2001 Internet Software Consortium. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: tests.sh,v 1.22 2012/02/09 23:47:18 tbox Exp $ + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +status=0 +n=0 + +getsit() { + awk '$2 == "SIT:" { + print $3; + }' < $1 +} + +havetc() { + grep 'flags:.* tc[^;]*;' $1 > /dev/null +} + +n=`expr $n + 1` +echo "I:checking SIT token returned to empty SIT option ($n)" +ret=0 +$DIG +qr +sit version.bind txt ch @10.53.0.1 -p 5300 > dig.out.test$n +grep SIT: dig.out.test$n > /dev/null || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:checking response size without SIT ($n)" +ret=0 +$DIG large.example txt @10.53.0.1 -p 5300 +ignore > dig.out.test$n +havetc dig.out.test$n || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:checking response size without valid SIT ($n)" +ret=0 +$DIG +sit large.example txt @10.53.0.1 -p 5300 +ignore > dig.out.test$n +havetc dig.out.test$n || ret=1 +grep ";; SIT client cookie part match" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:checking response size with SIT ($n)" +ret=0 +$DIG +sit large.example txt @10.53.0.1 -p 5300 > dig.out.test$n.l +sit=`getsit dig.out.test$n.l` +$DIG +qr +sit=$sit large.example txt @10.53.0.1 -p 5300 +ignore > dig.out.test$n +havetc dig.out.test$n && ret=1 +grep ";; SIT client cookie part match" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:checking response size with SIT recursive ($n)" +ret=0 +$DIG +qr +sit=$sit large.xxx txt @10.53.0.1 -p 5300 +ignore > dig.out.test$n +havetc dig.out.test$n && ret=1 +grep ";; SIT client cookie part match" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:checking for SIT value in adb ($n)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 dumpdb +sleep 1 +grep "10.53.0.2.*\[sit=" ns1/named_dump.db > /dev/null|| ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:exit status: $status" +exit $status diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index bd0a5fee41a..aefe0de1e9f 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -189,8 +189,9 @@ sendquery(isc_task_t *task, isc_event_t *event) { request = NULL; result = dns_request_create(requestmgr, query, &address, - 0, initialkey, TIMEOUT, task, - recvquery, query, &request); + DNS_REQUESTOPT_TCP, initialkey, + TIMEOUT, task, recvquery, query, + &request); CHECK("dns_request_create", result); } diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index 4c5f2c5027f..c956b18399d 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -132,8 +132,8 @@ sendquery(isc_task_t *task, isc_event_t *event) { request = NULL; result = dns_request_create(requestmgr, query, &address, - 0, tsigkey, TIMEOUT, task, - recvquery, query, &request); + DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, + task, recvquery, query, &request); CHECK("dns_request_create", result); } diff --git a/config.h.in b/config.h.in index 285d9299ae0..c6dd7318120 100644 --- a/config.h.in +++ b/config.h.in @@ -147,6 +147,9 @@ int sigwait(const unsigned int *set, int *sig); /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* Use AES for Source Identity Token generation */ +#undef AES_SIT + /* Define to enable the "filter-aaaa-on-v4" and "filter-aaaa-on-v6" options. */ #undef ALLOW_FILTER_AAAA @@ -170,6 +173,9 @@ int sigwait(const unsigned int *set, int *sig); /* Define to enable rpz-nsip rules. */ #undef ENABLE_RPZ_NSIP +/* Define to enable 'sit' support. */ +#undef ENABLE_SIT + /* Solaris hack to get select_large_fdset. */ #undef FD_SETSIZE @@ -422,6 +428,12 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP +/* Use HMAC-SHA1 for Source Identity Token generation */ +#undef HMAC_SHA1_SIT + +/* Use HMAC-SHA256 for Source Identity Token generation */ +#undef HMAC_SHA256_SIT + /* return type of gai_strerror */ #undef IRS_GAISTRERROR_RETURN_T diff --git a/configure b/configure index 598d044875e..dce84f9f533 100755 --- a/configure +++ b/configure @@ -700,6 +700,8 @@ XSLTPROC W3M PDFLATEX LATEX +HAVE_SIT +ISC_PLATFORM_USESIT ISC_ARCH_DIR ISC_PLATFORM_USEMACASM ISC_PLATFORM_USESTDASM @@ -816,6 +818,7 @@ PKCS11_TOOLS USE_PKCS11 ISC_OPENSSL_LIBS ISC_OPENSSL_INC +ISC_PLATFORM_OPENSSLAES ISC_PLATFORM_OPENSSLHASH OPENSSL_GOST OPENSSL_ECDSA @@ -983,6 +986,8 @@ with_ecdsa with_gost enable_openssl_version_check enable_openssl_hash +enable_openssl_aes +with_sit_alg with_libxml2 with_libjson enable_largefile @@ -1002,6 +1007,7 @@ enable_fixed_rrset enable_rpz_nsip enable_rpz_nsdname enable_filter_aaaa +enable_sit with_docbook_xsl with_idn with_libiconv @@ -1652,25 +1658,25 @@ Optional Features: --enable-threads enable multithreading --enable-native-pkcs11 use native PKCS11 for all crypto [default=no] --enable-openssl-version-check - Check OpenSSL Version [default=yes] + check OpenSSL version [default=yes] --enable-openssl-hash use OpenSSL for hash functions [default=no] + --enable-openssl-aes use OpenSSL for aes [default=no] --enable-largefile 64-bit file support --enable-backtrace log stack backtrace on abort [default=yes] --enable-symtable use internal symbol table for backtrace [all|minimal(default)|none] --enable-ipv6 use IPv6 default=autodetect - --enable-getifaddrs Enable the use of getifaddrs() [yes|no]. + --enable-getifaddrs enable the use of getifaddrs() [yes|no]. --disable-isc-spnego use SPNEGO from GSSAPI library --disable-chroot disable chroot --disable-linux-caps disable linux capabilities --enable-atomic enable machine specific atomic operations [default=autodetect] - --enable-fixed-rrset enable fixed rrset ordering - [default=no] + --enable-fixed-rrset enable fixed rrset ordering [default=no] --disable-rpz-nsip disable rpz-nsip rules [default=enabled] --disable-rpz-nsdname disable rpz-nsdname rules [default=enabled] - --enable-filter-aaaa enable filtering of AAAA records - [default=no] + --enable-filter-aaaa enable filtering of AAAA records [default=no] + --enable-sit enable source identity token [default=no] --enable-full-report report values of all configure options Optional Packages: @@ -1681,7 +1687,7 @@ Optional Packages: --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). - --with-python=PATH Specify path to python interpreter + --with-python=PATH specify path to python interpreter --with-geoip=PATH Build with GeoIP support (yes|no|path) --with-gssapi=PATH Specify path for system-supplied GSSAPI [default=yes] --with-randomdev=PATH Specify path for random device @@ -1692,19 +1698,20 @@ Optional Packages: (PATH is for the PKCS11 provider) --with-ecdsa Crypto ECDSA --with-gost Crypto GOST yes|no|raw|asn1. - --with-libxml2=PATH Build with libxml2 library yes|no|path - --with-libjson=PATH Build with libjson0 library yes|no|path + --with-sit-alg=ALG choose the algorithm for SIT [aes|sha1|sha256] + --with-libxml2=PATH build with libxml2 library yes|no|path + --with-libjson=PATH build with libjson0 library yes|no|path --with-purify=PATH use Rational purify --with-kame=PATH use Kame IPv6 default path /usr/local/v6 --with-readline=LIBSPEC specify readline library default -lreadline - --with-docbook-xsl=PATH Specify path for Docbook-XSL stylesheets + --with-docbook-xsl=PATH specify path for Docbook-XSL stylesheets --with-idn=MPREFIX enable IDN support using idnkit default PREFIX --with-libiconv=IPREFIX GNU libiconv are in IPREFIX default PREFIX --with-iconv=LIBSPEC specify iconv library default -liconv --with-idnlib=ARG specify libidnkit - --with-atf=ARG Automated Test Framework support - --with-dlopen=ARG Support dynamically loadable DLZ drivers + --with-atf=ARG support Automated Test Framework + --with-dlopen=ARG support dynamically loadable DLZ drivers --with-dlz-postgres=PATH Build with Postgres DLZ driver yes|no|path. (Required to use Postgres with DLZ) --with-dlz-mysql=PATH Build with MySQL DLZ driver yes|no|path. @@ -1719,7 +1726,7 @@ Optional Packages: (Required to use ODBC with DLZ) --with-dlz-stub=PATH Build with stub DLZ driver yes|no. (Required to use stub driver with DLZ) - --with-make-clean Run "make clean" at end of configure [yes|no]. + --with-make-clean run "make clean" at end of configure [yes|no] Some influential environment variables: CC C compiler command @@ -11381,6 +11388,7 @@ yes) test "${enable_filter_aaaa+set}" = set || enable_filter_aaaa=yes test "${with_dlz_filesystem+set}" = set || with_dlz_filesystem=yes test "${enable_symtable+set}" = set || enable_symtable=all + test "${enable_sit+set}" = set || enable_sit=yes ;; esac # @@ -15607,7 +15615,7 @@ esac DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DST_OPENSSL_LIBS" # -# Use OpenSSL for hash functions +# Use OpenSSL for hash functions and/or aes # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for using OpenSSL for hash functions" >&5 @@ -15619,6 +15627,51 @@ else want_openssl_hash="no" fi + +# Check whether --enable-openssl-aes was given. +if test "${enable_openssl_aes+set}" = set; then : + enableval=$enable_openssl_aes; want_openssl_aes="$enableval" +else + want_openssl_aes="no" +fi + + +# +# Source Identity Token algorithm choice +# + +# Check whether --with-sit-alg was given. +if test "${with_sit_alg+set}" = set; then : + withval=$with_sit_alg; with_sit_alg="$withval" +else + with_sit_alg="aes" +fi + + +case $with_sit_alg in + *1) + with_sit_alg="sha1" + want_openssl_hash="yes" + +$as_echo "#define HMAC_SHA1_SIT 1" >>confdefs.h + + ;; + *2*) + with_sit_alg="sha256" + want_openssl_hash="yes" + +$as_echo "#define HMAC_SHA256_SIT 1" >>confdefs.h + + ;; + *) + with_sit_alg="aes" + want_openssl_aes="yes" + +$as_echo "#define AES_SIT 1" >>confdefs.h + + ;; +esac + case $want_openssl_hash in yes) if test "$CRYPTO" = "" @@ -15639,6 +15692,20 @@ $as_echo "no" >&6; } ISC_OPENSSL_LIBS="" ;; esac +case $want_openssl_aes in + yes) + if test "$CRYPTO" = "" + then + as_fn_error $? "No OpenSSL for AES" "$LINENO" 5 + fi + ISC_PLATFORM_OPENSSLAES="#define ISC_PLATFORM_OPENSSLAES 1" + ISC_OPENSSL_INC="$DST_OPENSSL_INC" + ;; + no) + ISC_PLATFORM_OPENSSLAES="#undef ISC_PLATFORM_OPENSSLAES" + ;; +esac + @@ -18941,6 +19008,37 @@ $as_echo "#define ALLOW_FILTER_AAAA 1" >>confdefs.h ;; esac +# +# Enable Source Identity Token support +# +# Check whether --enable-sit was given. +if test "${enable_sit+set}" = set; then : + enableval=$enable_sit; enable_sit="$enableval" +else + enable_sit="no" +fi + + +ISC_PLATFORM_USESIT="#undef ISC_PLATFORM_USESIT" +HAVE_SIT= + +case "$enable_sit" in +yes) + +$as_echo "#define ENABLE_SIT 1" >>confdefs.h + + ISC_PLATFORM_USESIT="#define ISC_PLATFORM_USESIT 1" + HAVE_SIT=1 + ;; +no) + ;; +*) + as_fn_error $? "\"enable-sit requires yes or no\"" "$LINENO" 5 + ;; +esac + + + # # The following sets up how non-blocking i/o is established. # Sunos, cygwin and solaris 2.x (x<5) require special handling. @@ -19709,9 +19807,6 @@ $as_echo "#define ATF_TEST 1" >>confdefs.h STD_CINCLUDES="$STD_CINCLUDES -I$atf/include" ATFBIN="$atf/bin" ATFLIBS="-L$atf/lib -latf-c" - if test "$want_openssl_hash" = yes; then - ATFLIBS="-L$atf/lib -latf-c $DNS_CRYPTO_LIBS" - fi UNITTESTS=tests fi @@ -20996,7 +21091,7 @@ ac_config_commands="$ac_config_commands chmod" # elsewhere if there's a good reason for doing so. # -ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delve/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh" +ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/delve/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/pkcs11/Makefile bin/tests/pkcs11/benchmarks/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dlzredir/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/geoip/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/sit/prereq.sh bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/scripts/check-secure-delegation.pl contrib/scripts/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/include/pk11/Makefile lib/isc/include/pkcs11/Makefile lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile lib/samples/Makefile lib/samples/Makefile-postinstall unit/Makefile unit/unittest.sh" # @@ -22047,6 +22142,7 @@ do "bin/tests/system/geoip/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/geoip/Makefile" ;; "bin/tests/system/inline/checkdsa.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/inline/checkdsa.sh" ;; "bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;; + "bin/tests/system/sit/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/sit/prereq.sh" ;; "bin/tests/system/rpz/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rpz/Makefile" ;; "bin/tests/system/rsabigexponent/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/rsabigexponent/Makefile" ;; "bin/tests/system/tkey/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/tkey/Makefile" ;; @@ -23427,6 +23523,12 @@ echo "Optional features enabled:" $use_threads && echo " Multiprocessing support (--enable-threads)" test "$use_geoip" = "no" || echo " GeoIP access control (--with-geoip)" test "$use_gssapi" = "no" || echo " GSS-API (--with-gssapi)" +if test "$enable_sit" != "no"; then + echo " Source Identity Token support (--enable-sit)" + if test "$enable_full_report" = "yes" -o "$with_sit_alg" != "aes"; then + echo " Algorithm: $with_sit_alg" + fi +fi # these lines are only printed if run with --enable-full-report if test "$enable_full_report" = "yes"; then @@ -23490,6 +23592,8 @@ test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \ test "$use_geoip" = "no" && echo " GeoIP access control (--with-geoip)" test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)" +test "$enable_sit" = "no" && echo " Source Identity Token support (--enable-sit)" + test "$enable_fixed" = "yes" || \ echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)" diff --git a/configure.in b/configure.in index 6f31037b9c0..e7dd0587827 100644 --- a/configure.in +++ b/configure.in @@ -74,6 +74,7 @@ yes) test "${enable_filter_aaaa+set}" = set || enable_filter_aaaa=yes test "${with_dlz_filesystem+set}" = set || with_dlz_filesystem=yes test "${enable_symtable+set}" = set || enable_symtable=all + test "${enable_sit+set}" = set || enable_sit=yes ;; esac # @@ -136,7 +137,7 @@ AC_SUBST(PERL) # If python is unavailable, we simply don't build those. # AC_ARG_WITH(python, -[ --with-python=PATH Specify path to python interpreter], +[ --with-python=PATH specify path to python interpreter], use_python="$withval", use_python="unspec") case "$use_python" in @@ -1335,7 +1336,7 @@ shared library configuration (e.g., LD_LIBRARY_PATH).)], AC_ARG_ENABLE(openssl-version-check, [AC_HELP_STRING([--enable-openssl-version-check], - [Check OpenSSL Version @<:@default=yes@:>@])]) + [check OpenSSL version @<:@default=yes@:>@])]) case "$enable_openssl_version_check" in yes|'') AC_MSG_CHECKING(OpenSSL library version) @@ -1516,13 +1517,46 @@ AC_SUBST(OPENSSL_GOST) DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DST_OPENSSL_LIBS" # -# Use OpenSSL for hash functions +# Use OpenSSL for hash functions and/or aes # AC_MSG_CHECKING(for using OpenSSL for hash functions) AC_ARG_ENABLE(openssl-hash, [ --enable-openssl-hash use OpenSSL for hash functions [[default=no]]], want_openssl_hash="$enableval", want_openssl_hash="no") + +AC_ARG_ENABLE(openssl-aes, + [ --enable-openssl-aes use OpenSSL for aes [[default=no]]], + want_openssl_aes="$enableval", want_openssl_aes="no") + +# +# Source Identity Token algorithm choice +# +AC_ARG_WITH(sit-alg, + [ --with-sit-alg=ALG choose the algorithm for SIT [[aes|sha1|sha256]]], + with_sit_alg="$withval", with_sit_alg="aes") + +case $with_sit_alg in + *1) + with_sit_alg="sha1" + want_openssl_hash="yes" + AC_DEFINE(HMAC_SHA1_SIT, 1, + [Use HMAC-SHA1 for Source Identity Token generation]) + ;; + *2*) + with_sit_alg="sha256" + want_openssl_hash="yes" + AC_DEFINE(HMAC_SHA256_SIT, 1, + [Use HMAC-SHA256 for Source Identity Token generation]) + ;; + *) + with_sit_alg="aes" + want_openssl_aes="yes" + AC_DEFINE(AES_SIT, 1, + [Use AES for Source Identity Token generation]) + ;; +esac + case $want_openssl_hash in yes) if test "$CRYPTO" = "" @@ -1541,7 +1575,21 @@ case $want_openssl_hash in ISC_OPENSSL_LIBS="" ;; esac +case $want_openssl_aes in + yes) + if test "$CRYPTO" = "" + then + AC_MSG_ERROR([No OpenSSL for AES]) + fi + ISC_PLATFORM_OPENSSLAES="#define ISC_PLATFORM_OPENSSLAES 1" + ISC_OPENSSL_INC="$DST_OPENSSL_INC" + ;; + no) + ISC_PLATFORM_OPENSSLAES="#undef ISC_PLATFORM_OPENSSLAES" + ;; +esac AC_SUBST(ISC_PLATFORM_OPENSSLHASH) +AC_SUBST(ISC_PLATFORM_OPENSSLAES) AC_SUBST(ISC_OPENSSL_INC) AC_SUBST(ISC_OPENSSL_LIBS) @@ -1720,7 +1768,7 @@ fi # AC_MSG_CHECKING(for libxml2 library) AC_ARG_WITH(libxml2, -[ --with-libxml2[=PATH] Build with libxml2 library [yes|no|path]], +[ --with-libxml2[=PATH] build with libxml2 library [yes|no|path]], use_libxml2="$withval", use_libxml2="auto") case "$use_libxml2" in @@ -1762,7 +1810,7 @@ fi # AC_MSG_CHECKING(for json library) AC_ARG_WITH(libjson, -[ --with-libjson[=PATH] Build with libjson0 library [yes|no|path]], +[ --with-libjson[=PATH] build with libjson0 library [yes|no|path]], use_libjson="$withval", use_libjson="auto") have_libjson="" @@ -2626,7 +2674,7 @@ AC_SUBST(ISC_LWRES_GETNAMEINFOPROTO) AC_SUBST(ISC_IRS_GETNAMEINFOSOCKLEN) AC_ARG_ENABLE(getifaddrs, -[ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no]].], +[ --enable-getifaddrs enable the use of getifaddrs() [[yes|no]].], want_getifaddrs="$enableval", want_getifaddrs="yes") # @@ -3294,8 +3342,7 @@ AC_SUBST(ISC_ARCH_DIR) # Activate "rrset-order fixed" or not? # AC_ARG_ENABLE(fixed-rrset, - [ --enable-fixed-rrset enable fixed rrset ordering - [[default=no]]], + [ --enable-fixed-rrset enable fixed rrset ordering [[default=no]]], enable_fixed="$enableval", enable_fixed="no") case "$enable_fixed" in @@ -3349,8 +3396,7 @@ esac # Activate "filter-aaaa-on-v4/v6" or not? # AC_ARG_ENABLE(filter-aaaa, - [ --enable-filter-aaaa enable filtering of AAAA records - [[default=no]]], + [ --enable-filter-aaaa enable filtering of AAAA records [[default=no]]], enable_filter="$enableval", enable_filter="no") case "$enable_filter" in @@ -3364,6 +3410,31 @@ case "$enable_filter" in ;; esac +# +# Enable Source Identity Token support +# +AC_ARG_ENABLE(sit, + [ --enable-sit enable source identity token [[default=no]]], + enable_sit="$enableval", enable_sit="no") + +ISC_PLATFORM_USESIT="#undef ISC_PLATFORM_USESIT" +HAVE_SIT= + +case "$enable_sit" in +yes) + AC_DEFINE(ENABLE_SIT, 1, [Define to enable 'sit' support.]) + ISC_PLATFORM_USESIT="#define ISC_PLATFORM_USESIT 1" + HAVE_SIT=1 + ;; +no) + ;; +*) + AC_MSG_ERROR("enable-sit requires yes or no") + ;; +esac +AC_SUBST(ISC_PLATFORM_USESIT) +AC_SUBST(HAVE_SIT) + # # The following sets up how non-blocking i/o is established. # Sunos, cygwin and solaris 2.x (x<5) require special handling. @@ -3476,7 +3547,7 @@ AC_SUBST($1) # AC_MSG_CHECKING(for Docbook-XSL path) AC_ARG_WITH(docbook-xsl, -[ --with-docbook-xsl=PATH Specify path for Docbook-XSL stylesheets], +[ --with-docbook-xsl=PATH specify path for Docbook-XSL stylesheets], docbook_path="$withval", docbook_path="auto") case "$docbook_path" in auto) @@ -3614,7 +3685,7 @@ AC_SUBST(IDNLIBS) # Check whether to build Automated Test Framework unit tests # AC_ARG_WITH(atf, - [ --with-atf=ARG Automated Test Framework support], + [ --with-atf=ARG support Automated Test Framework], atf="$withval", atf="no") if test "$atf" = yes; then atf=`pwd`/unit/atf @@ -3640,9 +3711,6 @@ if test "$atf" != no; then STD_CINCLUDES="$STD_CINCLUDES -I$atf/include" ATFBIN="$atf/bin" ATFLIBS="-L$atf/lib -latf-c" - if test "$want_openssl_hash" = yes; then - ATFLIBS="-L$atf/lib -latf-c $DNS_CRYPTO_LIBS" - fi UNITTESTS=tests fi AC_SUBST(ATFBIN) @@ -3778,7 +3846,7 @@ SO_LD="" SO_TARGETS="" AC_ARG_WITH(dlopen, - [ --with-dlopen=ARG Support dynamically loadable DLZ drivers], + [ --with-dlopen=ARG support dynamically loadable DLZ drivers], dlopen="$withval", dlopen="yes") case $host in @@ -4096,6 +4164,7 @@ AC_CONFIG_FILES([ bin/tests/system/geoip/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile + bin/tests/system/sit/prereq.sh bin/tests/system/rpz/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile @@ -4185,7 +4254,7 @@ AC_OUTPUT # Now that the Makefiles exist we can ensure that everything is rebuilt. # AC_ARG_WITH(make-clean, -[ --with-make-clean Run "make clean" at end of configure [[yes|no]].], +[ --with-make-clean run "make clean" at end of configure [[yes|no]]], make_clean="$withval", make_clean="yes") case "$make_clean" in yes) @@ -4203,6 +4272,12 @@ echo "Optional features enabled:" $use_threads && echo " Multiprocessing support (--enable-threads)" test "$use_geoip" = "no" || echo " GeoIP access control (--with-geoip)" test "$use_gssapi" = "no" || echo " GSS-API (--with-gssapi)" +if test "$enable_sit" != "no"; then + echo " Source Identity Token support (--enable-sit)" + if test "$enable_full_report" = "yes" -o "$with_sit_alg" != "aes"; then + echo " Algorithm: $with_sit_alg" + fi +fi # these lines are only printed if run with --enable-full-report if test "$enable_full_report" = "yes"; then @@ -4266,6 +4341,8 @@ test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \ test "$use_geoip" = "no" && echo " GeoIP access control (--with-geoip)" test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)" +test "$enable_sit" = "no" && echo " Source Identity Token support (--enable-sit)" + test "$enable_fixed" = "yes" || \ echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)" diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 84ad97f747d..b99e75a725c 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -4766,6 +4766,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] multiple-cnames yes_or_no; notify yes_or_no | explicit | master-only; recursion yes_or_no; + request-sit yes_or_no; request-nsid yes_or_no; rfc2308-type1 yes_or_no; use-id-pool yes_or_no; @@ -6228,6 +6229,35 @@ options { + + request-sit + + If yes, then a SIT (Source Identity + Token) EDNS option is sent along with the query. If the + resolver has previously talked to the server, the SIT + returned in the previous transaction is sent. This + is used by the server to determine whether the resolver + has talked to it before. A resolver sending the corret + SIT is assumed not to be an off-path attacker sending a + spoofed-source query; the query is therefore unlikely to + be part of a reflection/amplification attack: resolvers + sending a correct SIT option are not subject to response + rate limiting (RRL). Resolvers which do not send a correct + SIT option may be limited to receiving smaller responses + via the nosit-udp-size option. + + + + + sit-secret + + If set, this is a shared secret used for generating and + verifying Source Identity Token EDNS options within a + anycast cluster. If not set the system will generation + a random secret at startup. + + + rfc2308-type1 @@ -10199,6 +10229,7 @@ rate-limit { request-ixfr yes_or_no ; edns yes_or_no ; edns-udp-size number ; + nosit-udp-size number ; max-udp-size number ; transfers number ; transfer-format ( one-answer | many-answers ) ; ] @@ -10324,6 +10355,14 @@ rate-limit { replies from named. + + The nosit-udp-size option sets the + maximum size of udp responses that will be sent to + queries without a valid source identity token. The command + max-udp-size option may further limit + the response size. + + The server supports two zone transfer methods. The first, one-answer, uses one DNS message per resource record transferred. many-answers packs diff --git a/doc/misc/options b/doc/misc/options index 33718f74b88..39d09f10906 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -140,9 +140,9 @@ options { fake-iquery ; // obsolete fetch-glue ; // obsolete files ; - filter-aaaa { ; ... }; // not configured - filter-aaaa-on-v4 ; // not configured - filter-aaaa-on-v6 ; // not configured + filter-aaaa { ; ... }; + filter-aaaa-on-v4 ; + filter-aaaa-on-v6 ; flush-zones-on-shutdown ; forward ( first | only ); forwarders [ port ] [ dscp ] { ( @@ -161,6 +161,8 @@ options { ; ... }; listen-on-v6 [ port ] [ dscp ] { ; ... }; + sit-secret ; + nosit-udp-size ; maintain-ixfr-base ; // obsolete managed-keys-directory ; masterfile-format ( text | raw | map ); @@ -230,6 +232,7 @@ options { recursion ; recursive-clients ; request-ixfr ; + request-sit ; request-nsid ; reserved-sockets ; resolver-query-timeout ; @@ -304,6 +307,8 @@ server { query-source ; query-source-v6 ; request-ixfr ; + request-sit ; + request-nsid ; support-ixfr ; // obsolete transfer-format ( many-answers | one-answer ); transfer-source ( | * ) [ port ( | * ) ] [ @@ -400,9 +405,9 @@ view { empty-server ; empty-zones-enable ; fetch-glue ; // obsolete - filter-aaaa { ; ... }; // not configured - filter-aaaa-on-v4 ; // not configured - filter-aaaa-on-v6 ; // not configured + filter-aaaa { ; ... }; + filter-aaaa-on-v4 ; + filter-aaaa-on-v6 ; forward ( first | only ); forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; @@ -414,6 +419,7 @@ view { }; key-directory ; lame-ttl ; + nosit-udp-size ; maintain-ixfr-base ; // obsolete managed-keys { ; ... }; @@ -475,6 +481,7 @@ view { }; recursion ; request-ixfr ; + request-sit ; request-nsid ; resolver-query-timeout ; response-policy { zone [ policy ( given | disabled @@ -503,6 +510,8 @@ view { query-source ; query-source-v6 ; request-ixfr ; + request-sit ; + request-nsid ; support-ixfr ; // obsolete transfer-format ( many-answers | one-answer ); transfer-source ( | * ) [ port ( | diff --git a/lib/dns/adb.c b/lib/dns/adb.c index e411e274ab5..f6d239137e5 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -255,6 +255,8 @@ struct dns_adbentry { unsigned char to1232; /* IPv6 nofrag */ unsigned char to512; /* plain DNS */ isc_sockaddr_t sockaddr; + unsigned char * sit; + isc_uint16_t sitlen; isc_stdtime_t expires; /*%< @@ -1802,6 +1804,8 @@ new_adbentry(dns_adb_t *adb) { e->to1432 = 0; e->to1232 = 0; e->to512 = 0; + e->sit = NULL; + e->sitlen = 0; isc_random_get(&r); e->srtt = (r & 0x1f) + 1; e->expires = 0; @@ -1838,6 +1842,9 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) { e->magic = 0; + if (e->sit != NULL) + isc_mem_put(adb->mctx, e->sit, e->sitlen); + li = ISC_LIST_HEAD(e->lameinfo); while (li != NULL) { ISC_LIST_UNLINK(e->lameinfo, li, plink); @@ -3425,6 +3432,16 @@ dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug, entry->to512, entry->plain, entry->plainto); if (entry->udpsize != 0U) fprintf(f, " [udpsize %u]", entry->udpsize); +#ifdef ISC_PLATFORM_USESIT + if (entry->sit != NULL) { + unsigned int i; + fprintf(f, " [sit="); + for (i = 0; i < entry->sitlen; i++) + fprintf(f, "%02x", entry->sit[i]); + fprintf(f, "]"); + } +#endif + if (entry->expires != 0) fprintf(f, " [ttl %d]", entry->expires - now); fprintf(f, "\n"); @@ -4086,6 +4103,7 @@ dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { bucket = addr->entry->lock_bucket; LOCK(&adb->entrylocks[bucket]); + addr->entry->plain++; if (addr->entry->plain == 0xff) { addr->entry->edns >>= 1; @@ -4242,6 +4260,59 @@ dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { return (size); } +void +dns_adb_setsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr, + const unsigned char *sit, size_t len) +{ + int bucket; + + REQUIRE(DNS_ADB_VALID(adb)); + REQUIRE(DNS_ADBADDRINFO_VALID(addr)); + + bucket = addr->entry->lock_bucket; + LOCK(&adb->entrylocks[bucket]); + + if (addr->entry->sit != NULL && + (sit == NULL || len != addr->entry->sitlen)) { + isc_mem_put(adb->mctx, addr->entry->sit, addr->entry->sitlen); + addr->entry->sit = NULL; + addr->entry->sitlen = 0; + } + + if (addr->entry->sit == NULL && sit != NULL && len != 0U) { + addr->entry->sit = isc_mem_get(adb->mctx, len); + if (addr->entry->sit != NULL) + addr->entry->sitlen = len; + } + + if (addr->entry->sit != NULL) + memcpy(addr->entry->sit, sit, len); + UNLOCK(&adb->entrylocks[bucket]); +} + +size_t +dns_adb_getsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr, + unsigned char *sit, size_t len) +{ + int bucket; + + REQUIRE(DNS_ADB_VALID(adb)); + REQUIRE(DNS_ADBADDRINFO_VALID(addr)); + + bucket = addr->entry->lock_bucket; + LOCK(&adb->entrylocks[bucket]); + if (sit != NULL && addr->entry->sit != NULL && + len >= addr->entry->sitlen) + { + memcpy(sit, addr->entry->sit, addr->entry->sitlen); + len = addr->entry->sitlen; + } else + len = 0; + UNLOCK(&adb->entrylocks[bucket]); + + return (len); +} + isc_result_t dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa, dns_adbaddrinfo_t **addrp, isc_stdtime_t now) diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index 0d4891a0437..4cc8c9edc8b 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -728,6 +728,32 @@ dns_adb_flushnames(dns_adb_t *adb, dns_name_t *name); *\li 'name' is valid. */ +void +dns_adb_setsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr, + const unsigned char *sit, size_t len); +/*%< + * Record the Source Identity Token (SIT) associated with this addresss. If + * sit is NULL or len is zero. The recorded SIT is cleared. + * + * Requires: + *\li 'adb' is valid. + *\li 'addr' is valid. + */ + +size_t +dns_adb_getsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr, + unsigned char *sit, size_t len); +/* + * Retieve the saved SIT value and store it in 'sit' which has size 'len'. + * + * Requires: + *\li 'adb' is valid. + *\li 'addr' is valid. + * + * Returns: + * The size of the sit token or zero if it doesn't fit in the buffer + * or it doesn't exist. + */ ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 889a7c31c4a..6461b52ffbe 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -106,6 +106,8 @@ /*%< EDNS0 extended OPT codes */ #define DNS_OPT_NSID 0x0003 /*%< NSID opt code */ #define DNS_OPT_CLIENT_SUBNET 0x0008 /*%< client subnet opt code */ +/*%< Experimental options [65001...65534] as per RFC6891 */ +#define DNS_OPT_SIT 65001 /*%< SIT opt code */ #define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD) #define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO) @@ -1391,7 +1393,6 @@ dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt, * \li other. */ - ISC_LANG_ENDDECLS #endif /* DNS_MESSAGE_H */ diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h index 49c79c15b7d..619697ceb09 100644 --- a/lib/dns/include/dns/peer.h +++ b/lib/dns/include/dns/peer.h @@ -74,6 +74,7 @@ struct dns_peer { isc_boolean_t request_ixfr; isc_boolean_t support_edns; isc_boolean_t request_nsid; + isc_boolean_t request_sit; dns_name_t *key; isc_sockaddr_t *transfer_source; isc_dscp_t transfer_dscp; @@ -159,6 +160,12 @@ dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval); isc_result_t dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval); +isc_result_t +dns_peer_setrequestsit(dns_peer_t *peer, isc_boolean_t newval); + +isc_result_t +dns_peer_getrequestsit(dns_peer_t *peer, isc_boolean_t *retval); + isc_result_t dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval); diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index a6b938e9cca..eeff364e419 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -66,8 +66,16 @@ enum { dns_resstatscounter_dispreqtcp = 32, dns_resstatscounter_buckets = 33, dns_resstatscounter_refused = 34, - +#ifdef ISC_PLATFORM_USESIT + dns_resstatscounter_sitcc = 35, + dns_resstatscounter_sitout = 36, + dns_resstatscounter_sitin = 37, + dns_resstatscounter_sitok = 38, + + dns_resstatscounter_max = 39, +#else dns_resstatscounter_max = 35, +#endif /* * DNSSEC stats. diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 676eef336dc..bba7e1aeb67 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -148,6 +148,7 @@ struct dns_view { dns_rrl_t * rrl; isc_boolean_t provideixfr; isc_boolean_t requestnsid; + isc_boolean_t requestsit; dns_ttl_t maxcachettl; dns_ttl_t maxncachettl; dns_ttl_t prefetch_trigger; @@ -163,6 +164,7 @@ struct dns_view { dns_name_t * dlv; dns_fixedname_t dlv_fixed; isc_uint16_t maxudp; + isc_uint16_t situdp; unsigned int maxbits; dns_aaaa_t v4_aaaa; dns_aaaa_t v6_aaaa; @@ -204,6 +206,8 @@ struct dns_view { char * new_zone_file; void * new_zone_config; void (*cfg_destroy)(void **); + + unsigned char secret[33]; /* Client secret */ }; #define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w') diff --git a/lib/dns/message.c b/lib/dns/message.c index 781ec2bc341..20358195ca4 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -3255,6 +3255,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, if (optcode == DNS_OPT_NSID) { ADD_STRING(target, "; NSID"); + } else if (optcode == DNS_OPT_SIT) { + ADD_STRING(target, "; SIT"); } else { ADD_STRING(target, "; OPT="); sprintf(buf, "%u", optcode); @@ -3267,10 +3269,30 @@ dns_message_pseudosectiontotext(dns_message_t *msg, optdata = isc_buffer_current(&optbuf); for (i = 0; i < optlen; i++) { - sprintf(buf, "%02x ", optdata[i]); + const char *sep; + switch (optcode) { + case DNS_OPT_SIT: + sep = ""; + break; + default: + sep = " "; + break; + } + sprintf(buf, "%02x%s", optdata[i], sep); ADD_STRING(target, buf); } + isc_buffer_forward(&optbuf, optlen); + + if (optcode == DNS_OPT_SIT) { + ADD_STRING(target, "\n"); + break; + } + + /* + * For non-SIT options, add a printable + * version + */ ADD_STRING(target, "(\""); for (i = 0; i < optlen; i++) { if (isprint(optdata[i])) @@ -3281,7 +3303,6 @@ dns_message_pseudosectiontotext(dns_message_t *msg, isc_buffer_putstr(target, "."); } ADD_STRING(target, "\")"); - isc_buffer_forward(&optbuf, optlen); } ADD_STRING(target, "\n"); } diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 3e4184e37ce..51081456868 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -43,6 +43,7 @@ #define SERVER_UDPSIZE_BIT 6 #define SERVER_MAXUDP_BIT 7 #define REQUEST_NSID_BIT 8 +#define REQUEST_SIT_BIT 9 static void peerlist_delete(dns_peerlist_t **list); @@ -447,6 +448,32 @@ dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval) { return (ISC_R_NOTFOUND); } +isc_result_t +dns_peer_setrequestsit(dns_peer_t *peer, isc_boolean_t newval) { + isc_boolean_t existed; + + REQUIRE(DNS_PEER_VALID(peer)); + + existed = DNS_BIT_CHECK(REQUEST_SIT_BIT, &peer->bitflags); + + peer->request_sit = newval; + DNS_BIT_SET(REQUEST_SIT_BIT, &peer->bitflags); + + return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); +} + +isc_result_t +dns_peer_getrequestsit(dns_peer_t *peer, isc_boolean_t *retval) { + REQUIRE(DNS_PEER_VALID(peer)); + REQUIRE(retval != NULL); + + if (DNS_BIT_CHECK(REQUEST_SIT_BIT, &peer->bitflags)) { + *retval = peer->request_nsid; + return (ISC_R_SUCCESS); + } else + return (ISC_R_NOTFOUND); +} + isc_result_t dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) { isc_boolean_t existed; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 4cb4515839f..e0c765d51ef 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -32,6 +32,12 @@ #include #include +#ifdef AES_SIT +#include +#else +#include +#endif + #include #include #include @@ -1733,6 +1739,83 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) { ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link); } +#ifdef ISC_PLATFORM_USESIT +static void +compute_cc(resquery_t *query, unsigned char *sit, size_t len) { +#ifdef AES_SIT + unsigned char digest[ISC_AES_BLOCK_LENGTH]; + unsigned char input[16]; + isc_netaddr_t netaddr; + unsigned int i; + + INSIST(len >= 8U); + + isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr); + switch (netaddr.family) { + case AF_INET: + memcpy(input, (unsigned char *)&netaddr.type.in, 4); + memset(input + 4, 0, 12); + break; + case AF_INET6: + memcpy(input, (unsigned char *)&netaddr.type.in6, 16); + break; + } + isc_aes128_crypt(query->fctx->res->view->secret, input, digest); + for (i = 0; i < 8; i++) + digest[i] ^= digest[i + 8]; + memcpy(sit, digest, 8); +#endif +#ifdef HMAC_SHA1_SIT + unsigned char digest[ISC_SHA1_DIGESTLENGTH]; + isc_netaddr_t netaddr; + isc_hmacsha1_t hmacsha1; + + INSIST(len >= 8U); + + isc_hmacsha1_init(&hmacsha1, query->fctx->res->view->secret, + ISC_SHA1_DIGESTLENGTH); + isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr); + switch (netaddr.family) { + case AF_INET: + isc_hmacsha1_update(&hmacsha1, + (unsigned char *)&netaddr.type.in, 4); + break; + case AF_INET6: + isc_hmacsha1_update(&hmacsha1, + (unsigned char *)&netaddr.type.in6, 16); + break; + } + isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest)); + memcpy(sit, digest, 8); + isc_hmacsha1_invalidate(&hmacsha1); +#endif +#ifdef HMAC_SHA256_SIT + unsigned char digest[ISC_SHA256_DIGESTLENGTH]; + isc_netaddr_t netaddr; + isc_hmacsha256_t hmacsha256; + + INSIST(len >= 8U); + + isc_hmacsha256_init(&hmacsha256, query->fctx->res->view->secret, + ISC_SHA256_DIGESTLENGTH); + isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr); + switch (netaddr.family) { + case AF_INET: + isc_hmacsha256_update(&hmacsha256, + (unsigned char *)&netaddr.type.in, 4); + break; + case AF_INET6: + isc_hmacsha256_update(&hmacsha256, + (unsigned char *)&netaddr.type.in6, 16); + break; + } + isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest)); + memcpy(sit, digest, 8); + isc_hmacsha256_invalidate(&hmacsha256); +#endif +} +#endif + static isc_result_t resquery_send(resquery_t *query) { fetchctx_t *fctx; @@ -1758,10 +1841,6 @@ resquery_send(resquery_t *query) { unsigned ednsopt = 0; isc_uint16_t hint = 0, udpsize = 0; /* No EDNS */ - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_format(&query->addrinfo->sockaddr, - addrbuf, sizeof(addrbuf)); - fctx = query->fctx; QTRACE("send"); @@ -1935,6 +2014,10 @@ resquery_send(resquery_t *query) { unsigned int version = 0; /* Default version. */ unsigned int flags = query->addrinfo->flags; isc_boolean_t reqnsid = res->view->requestnsid; +#ifdef ISC_PLATFORM_USESIT + isc_boolean_t reqsit = res->view->requestsit; + unsigned char sit[64]; +#endif if ((flags & FCTX_ADDRINFO_EDNSOK) != 0 && (query->options & DNS_FETCHOPT_EDNS512) == 0) { @@ -1974,9 +2057,13 @@ resquery_send(resquery_t *query) { version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT; } - /* request NSID for current view or peer? */ - if (peer != NULL) + /* Request NSID/SIT for current view or peer? */ + if (peer != NULL) { (void) dns_peer_getrequestnsid(peer, &reqnsid); +#ifdef ISC_PLATFORM_USESIT + (void) dns_peer_getrequestsit(peer, &reqsit); +#endif + } if (reqnsid) { INSIST(ednsopt < EDNSOPTS); ednsopts[ednsopt].code = DNS_OPT_NSID; @@ -1984,6 +2071,28 @@ resquery_send(resquery_t *query) { ednsopts[ednsopt].value = NULL; ednsopt++; } +#ifdef ISC_PLATFORM_USESIT + if (reqsit) { + INSIST(ednsopt < EDNSOPTS); + ednsopts[ednsopt].code = DNS_OPT_SIT; + ednsopts[ednsopt].length = + dns_adb_getsit(fctx->adb, + query->addrinfo, + sit, sizeof(sit)); + if (ednsopts[ednsopt].length != 0) { + ednsopts[ednsopt].value = sit; + inc_stats(fctx->res, + dns_resstatscounter_sitout); + } else { + compute_cc(query, sit, sizeof(sit)); + ednsopts[ednsopt].value = sit; + ednsopts[ednsopt].length = 8; + inc_stats(fctx->res, + dns_resstatscounter_sitcc); + } + ednsopt++; + } +#endif result = fctx_addopt(fctx->qmessage, version, udpsize, ednsopts, ednsopt); if (reqnsid && result == ISC_R_SUCCESS) { @@ -6896,6 +7005,11 @@ process_opt(resquery_t *query, dns_rdataset_t *opt) { isc_result_t result; isc_uint16_t optcode; isc_uint16_t optlen; +#ifdef ISC_PLATFORM_USESIT + unsigned char *sit; + dns_adbaddrinfo_t *addrinfo; + unsigned char cookie[8]; +#endif result = dns_rdataset_first(opt); if (result == ISC_R_SUCCESS) { @@ -6915,6 +7029,23 @@ process_opt(resquery_t *query, dns_rdataset_t *opt) { query->fctx->res->mctx); isc_buffer_forward(&optbuf, optlen); break; +#ifdef ISC_PLATFORM_USESIT + case DNS_OPT_SIT: + sit = isc_buffer_current(&optbuf); + compute_cc(query, cookie, sizeof(cookie)); + if (optlen >= 8U && + memcmp(cookie, sit, 8) == 0) { + inc_stats(query->fctx->res, + dns_resstatscounter_sitok); + addrinfo = query->addrinfo; + dns_adb_setsit(query->fctx->adb, + addrinfo, sit, optlen); + } + isc_buffer_forward(&optbuf, optlen); + inc_stats(query->fctx->res, + dns_resstatscounter_sitin); + break; +#endif default: isc_buffer_forward(&optbuf, optlen); break; diff --git a/lib/dns/view.c b/lib/dns/view.c index b6349e2201b..f0b323c6518 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -195,6 +195,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->flush = ISC_FALSE; view->dlv = NULL; view->maxudp = 0; + view->situdp = 0; view->maxbits = 0; view->v4_aaaa = dns_aaaa_ok; view->v6_aaaa = dns_aaaa_ok; @@ -203,6 +204,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_fixedname_init(&view->dlv_fixed); view->managed_keys = NULL; view->redirect = NULL; + view->requestnsid = ISC_FALSE; + view->requestsit = ISC_TRUE; view->new_zone_file = NULL; view->new_zone_config = NULL; view->cfg_destroy = NULL; diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 7614e7dd687..6dce1169e03 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -55,7 +55,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ # Alphabetically OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ \ - assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ + aes.@O@ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ bind9.@O@ buffer.@O@ bufferlist.@O@ \ commandline.@O@ crc64.@O@ error.@O@ event.@O@ \ hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ @@ -74,7 +74,7 @@ SYMTBLOBJS = backtrace-emptytbl.@O@ # Alphabetically SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ \ - assertions.c backtrace.c base32.c base64.c bind9.c \ + aes.c assertions.c backtrace.c base32.c base64.c bind9.c \ buffer.c bufferlist.c commandline.c crc64.c \ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ httpd.c inet_aton.c iterated_hash.c \ diff --git a/lib/isc/aes.c b/lib/isc/aes.c new file mode 100644 index 00000000000..e0bbf80e52b --- /dev/null +++ b/lib/isc/aes.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/*! \file isc/aes.c */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#ifdef ISC_PLATFORM_OPENSSLAES + +#ifndef EVP_AES + +#include + +void +isc_aes128_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + AES_KEY k; + + RUNTIME_CHECK(AES_set_encrypt_key(key, 128, &k) == 0); + AES_encrypt(in, out, &k); +} + +void +isc_aes192_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + AES_KEY k; + + RUNTIME_CHECK(AES_set_encrypt_key(key, 192, &k) == 0); + AES_encrypt(in, out, &k); +} + +void +isc_aes256_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + AES_KEY k; + + RUNTIME_CHECK(AES_set_encrypt_key(key, 256, &k) == 0); + AES_encrypt(in, out, &k); +} +#else + +#include + +void +isc_aes128_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + EVP_CIPHER_CTX c; + int len; + + EVP_CIPHER_CTX_init(&c); + RUNTIME_CHECK(EVP_EncryptInit(&c, EVP_aes_128_ecb(), key, NULL) == 1); + EVP_CIPHER_CTX_set_padding(&c, 0); + RUNTIME_CHECK(EVP_EncryptUpdate(&c, out, &len, in, + ISC_AES_BLOCK_LENGTH) == 1); + RUNTIME_CHECK(len == ISC_AES_BLOCK_LENGTH); + RUNTIME_CHECK(EVP_CIPHER_CTX_cleanup(&c) == 1); +} + +void +isc_aes192_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + EVP_CIPHER_CTX c; + int len; + + EVP_CIPHER_CTX_init(&c); + RUNTIME_CHECK(EVP_EncryptInit(&c, EVP_aes_192_ecb(), key, NULL) == 1); + EVP_CIPHER_CTX_set_padding(&c, 0); + RUNTIME_CHECK(EVP_EncryptUpdate(&c, out, &len, in, + ISC_AES_BLOCK_LENGTH) == 1); + RUNTIME_CHECK(len == ISC_AES_BLOCK_LENGTH); + RUNTIME_CHECK(EVP_CIPHER_CTX_cleanup(&c) == 1); +} + +void +isc_aes256_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out) +{ + EVP_CIPHER_CTX c; + int len; + + EVP_CIPHER_CTX_init(&c); + RUNTIME_CHECK(EVP_EncryptInit(&c, EVP_aes_256_ecb(), key, NULL) == 1); + EVP_CIPHER_CTX_set_padding(&c, 0); + RUNTIME_CHECK(EVP_EncryptUpdate(&c, out, &len, in, + ISC_AES_BLOCK_LENGTH) == 1); + RUNTIME_CHECK(len == ISC_AES_BLOCK_LENGTH); + RUNTIME_CHECK(EVP_CIPHER_CTX_cleanup(&c) == 1); +} +#endif + +#endif diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in index bc99bd1ac46..15ff1e62918 100644 --- a/lib/isc/include/isc/Makefile.in +++ b/lib/isc/include/isc/Makefile.in @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ # machine generated. The latter are handled specially in the # install target below. # -HEADERS = app.h assertions.h base64.h bind9.h boolean.h buffer.h \ +HEADERS = aes.h app.h assertions.h base64.h bind9.h boolean.h buffer.h \ bufferlist.h commandline.h entropy.h error.h event.h \ eventclass.h file.h formatcheck.h fsaccess.h \ hash.h heap.h hex.h hmacmd5.h hmacsha.h \ diff --git a/lib/isc/include/isc/aes.h b/lib/isc/include/isc/aes.h new file mode 100644 index 00000000000..1e3a9f4835c --- /dev/null +++ b/lib/isc/include/isc/aes.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/*! \file isc/aes.h */ + +#ifndef ISC_AES_H +#define ISC_AES_H 1 + +#include +#include +#include + +#ifdef ISC_PLATFORM_OPENSSLAES + +#define ISC_AES128_KEYLENGTH 16U +#define ISC_AES192_KEYLENGTH 24U +#define ISC_AES256_KEYLENGTH 32U +#define ISC_AES_BLOCK_LENGTH 16U + +ISC_LANG_BEGINDECLS + +void +isc_aes128_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out); + +void +isc_aes192_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out); + +void +isc_aes256_crypt(const unsigned char *key, const unsigned char *in, + unsigned char *out); + +ISC_LANG_ENDDECLS + +#endif /* ISC_PLATFORM_OPENSSLAES */ + +#endif /* ISC_AES_H */ diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index 07553e36b89..a26f12b47ab 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -311,12 +311,22 @@ */ @ISC_PLATFORM_OPENSSLHASH@ +/* + * Define if AES must be provided by OpenSSL. + */ +@ISC_PLATFORM_OPENSSLAES@ + /* * Defines for the noreturn attribute. */ @ISC_PLATFORM_NORETURN_PRE@ @ISC_PLATFORM_NORETURN_POST@ +/* + * Defined if we are enabling SIT (Source Identity Token). + */ +@ISC_PLATFORM_USESIT@ + /*** *** Windows dll support. ***/ diff --git a/lib/isc/tests/Makefile.in b/lib/isc/tests/Makefile.in index 7a0da96b5fa..997397d30db 100644 --- a/lib/isc/tests/Makefile.in +++ b/lib/isc/tests/Makefile.in @@ -29,7 +29,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I. -Iinclude ${ISC_INCLUDES} CDEFINES = -DTESTS="\"${top_builddir}/lib/isc/tests/\"" -ISCLIBS = ../libisc.@A@ +ISCLIBS = ../libisc.@A@ @DNS_CRYPTO_LIBS@ ISCDEPLIBS = ../libisc.@A@ LIBS = @LIBS@ @ATFLIBS@ @@ -39,8 +39,7 @@ SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \ lex_test.c \ sockaddr_test.c symtab_test.c task_test.c queue_test.c \ parse_test.c pool_test.c regex_test.c socket_test.c \ - safe_test.c \ - time_test.c + safe_test.c time_test.c aes_test.c SUBDIRS = TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \ @@ -48,7 +47,7 @@ TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \ sockaddr_test@EXEEXT@ symtab_test@EXEEXT@ task_test@EXEEXT@ \ queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \ regex_test@EXEEXT@ socket_test@EXEEXT@ safe_test@EXEEXT@ \ - time_test@EXEEXT@ + time_test@EXEEXT@ aes_test@EXEEXT@ @BIND9_MAKE_RULES@ @@ -104,6 +103,10 @@ time_test@EXEEXT@: time_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ time_test.@O@ ${ISCLIBS} ${LIBS} +aes_test@EXEEXT@: aes_test.@O@ ${ISCDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + aes_test.@O@ ${ISCLIBS} ${LIBS} + unit:: sh ${top_srcdir}/unit/unittest.sh diff --git a/lib/isc/tests/aes_test.c b/lib/isc/tests/aes_test.c new file mode 100644 index 00000000000..c9497b88f8d --- /dev/null +++ b/lib/isc/tests/aes_test.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/* ! \file */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ISC_PLATFORM_OPENSSLAES + +/* + * Test data from NIST KAT + */ + +isc_result_t +tohexstr(unsigned char *d, char *out); + +size_t +fromhexstr(const char *in, unsigned char *d); + +unsigned char plaintext[3 * ISC_AES_BLOCK_LENGTH]; +unsigned char ciphertext[ISC_AES_BLOCK_LENGTH]; +char str[2 * ISC_AES_BLOCK_LENGTH + 1]; +unsigned char key[ISC_AES256_KEYLENGTH + 1]; +size_t len; + +isc_result_t +tohexstr(unsigned char *d, char *out) { + isc_buffer_t b; + isc_region_t r; + + isc_buffer_init(&b, out, 2 * ISC_AES_BLOCK_LENGTH + 1); + r.base = d; + r.length = ISC_AES_BLOCK_LENGTH; + return (isc_hex_totext(&r, 0, "", &b)); +} + +size_t +fromhexstr(const char *in, unsigned char *d) +{ + isc_buffer_t b; + isc_result_t ret; + + isc_buffer_init(&b, d, ISC_AES256_KEYLENGTH + 1); + ret = isc_hex_decodestring(in, &b); + if (ret != ISC_R_SUCCESS) + return 0; + return isc_buffer_usedlength(&b); +} + +typedef struct aes_testcase { + const char *key; + const char *input; + const char *result; +} aes_testcase_t; + + +ATF_TC(isc_aes128); +ATF_TC_HEAD(isc_aes128, tc) { + atf_tc_set_md_var(tc, "descr", "AES 128 test vectors"); +} +ATF_TC_BODY(isc_aes128, tc) { + UNUSED(tc); + + aes_testcase_t testcases[] = { + /* Test 1 (KAT ECBVarTxt128 #3) */ + { + "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "96D9FD5CC4F07441727DF0F33E401A36" + }, + /* Test 2 (KAT ECBVarTxt128 #123) */ + { + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "F9B0FDA0C4A898F5B9E6F661C4CE4D07" + }, + /* Test 3 (KAT ECBVarKey128 #3) */ + { + "F0000000000000000000000000000000", + "00000000000000000000000000000000", + "970014D634E2B7650777E8E84D03CCD8" + }, + /* Test 4 (KAT ECBVarKey128 #123) */ + { + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "41C78C135ED9E98C096640647265DA1E" + }, + /* Test 5 (KAT ECBGFSbox128 #3) */ + { + "00000000000000000000000000000000", + "6A118A874519E64E9963798A503F1D35", + "DC43BE40BE0E53712F7E2BF5CA707209" + }, + /* Test 6 (KAT ECBKeySbox128 #3) */ + { + "B6364AC4E1DE1E285EAF144A2415F7A0", + "00000000000000000000000000000000", + "5D9B05578FC944B3CF1CCF0E746CD581" + }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + ATF_CHECK_EQ(len, ISC_AES128_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + ATF_CHECK_EQ(len, ISC_AES_BLOCK_LENGTH); + isc_aes128_crypt(key, plaintext, ciphertext); + ATF_CHECK(tohexstr(ciphertext, str) == ISC_R_SUCCESS); + ATF_CHECK_STREQ(str, testcase->result); + + testcase++; + } +} + +ATF_TC(isc_aes192); +ATF_TC_HEAD(isc_aes192, tc) { + atf_tc_set_md_var(tc, "descr", "AES 192 test vectors"); +} +ATF_TC_BODY(isc_aes192, tc) { + UNUSED(tc); + + aes_testcase_t testcases[] = { + /* Test 1 (KAT ECBVarTxt192 #3) */ + { + "000000000000000000000000000000000000000000000000", + "F0000000000000000000000000000000", + "2A560364CE529EFC21788779568D5555" + }, + /* Test 2 (KAT ECBVarTxt192 #123) */ + { + "000000000000000000000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "2AABB999F43693175AF65C6C612C46FB" + }, + /* Test 3 (KAT ECBVarKey192 #3) */ + { + "F00000000000000000000000000000000000000000000000", + "00000000000000000000000000000000", + "180B09F267C45145DB2F826C2582D35C" + }, + /* Test 4 (KAT ECBVarKey192 #187) */ + { + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "EACF1E6C4224EFB38900B185AB1DFD42" + }, + /* Test 5 (KAT ECBGFSbox192 #3) */ + { + "000000000000000000000000000000000000000000000000", + "51719783D3185A535BD75ADC65071CE1", + "4F354592FF7C8847D2D0870CA9481B7C" + }, + /* Test 6 (KAT ECBKeySbox192 #3) */ + { + "CD62376D5EBB414917F0C78F05266433DC9192A1EC943300", + "00000000000000000000000000000000", + "7F6C25FF41858561BB62F36492E93C29" + }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + ATF_CHECK_EQ(len, ISC_AES192_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + ATF_CHECK_EQ(len, ISC_AES_BLOCK_LENGTH); + isc_aes192_crypt(key, plaintext, ciphertext); + ATF_CHECK(tohexstr(ciphertext, str) == ISC_R_SUCCESS); + ATF_CHECK_STREQ(str, testcase->result); + + testcase++; + } +} + +ATF_TC(isc_aes256); +ATF_TC_HEAD(isc_aes256, tc) { + atf_tc_set_md_var(tc, "descr", "AES 256 test vectors"); +} +ATF_TC_BODY(isc_aes256, tc) { + UNUSED(tc); + + aes_testcase_t testcases[] = { + /* Test 1 (KAT ECBVarTxt256 #3) */ + { + "00000000000000000000000000000000" + "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "7F2C5ECE07A98D8BEE13C51177395FF7" + }, + /* Test 2 (KAT ECBVarTxt256 #123) */ + { + "00000000000000000000000000000000" + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "7240E524BC51D8C4D440B1BE55D1062C" + }, + /* Test 3 (KAT ECBVarKey256 #3) */ + { + "F0000000000000000000000000000000" + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "1C777679D50037C79491A94DA76A9A35" + }, + /* Test 4 (KAT ECBVarKey256 #251) */ + { + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "03720371A04962EAEA0A852E69972858" + }, + /* Test 5 (KAT ECBGFSbox256 #3) */ + { + "00000000000000000000000000000000" + "00000000000000000000000000000000", + "8A560769D605868AD80D819BDBA03771", + "38F2C7AE10612415D27CA190D27DA8B4" + }, + /* Test 6 (KAT ECBKeySbox256 #3) */ + { + "984CA75F4EE8D706F46C2D98C0BF4A45" + "F5B00D791C2DFEB191B5ED8E420FD627", + "00000000000000000000000000000000", + "4307456A9E67813B452E15FA8FFFE398" + }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + ATF_CHECK_EQ(len, ISC_AES256_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + ATF_CHECK_EQ(len, ISC_AES_BLOCK_LENGTH); + isc_aes256_crypt(key, plaintext, ciphertext); + ATF_CHECK(tohexstr(ciphertext, str) == ISC_R_SUCCESS); + ATF_CHECK_STREQ(str, testcase->result); + + testcase++; + } +} +#else +ATF_TC(untested); +ATF_TC_HEAD(untested, tc) { + atf_tc_set_md_var(tc, "descr", "skipping aes test"); +} +ATF_TC_BODY(untested, tc) { + UNUSED(tc); + atf_tc_skip("AES not available"); +} +#endif + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { +#ifdef ISC_PLATFORM_OPENSSLAES + ATF_TP_ADD_TC(tp, isc_aes128); + ATF_TP_ADD_TC(tp, isc_aes192); + ATF_TP_ADD_TC(tp, isc_aes256); +#else + ATF_TP_ADD_TC(tp, untested); +#endif + return (atf_no_error()); +} + diff --git a/lib/isc/win32/include/isc/platform.h.in b/lib/isc/win32/include/isc/platform.h.in index 9357baf87ae..05ef7040c42 100644 --- a/lib/isc/win32/include/isc/platform.h.in +++ b/lib/isc/win32/include/isc/platform.h.in @@ -109,6 +109,11 @@ */ @ISC_PLATFORM_NEEDSTRCASESTR@ +/* + * Define to enable Source Identity Token support. + */ +#define ISC_PLATFORM_USESIT 1 + /* * Set up a macro for importing and exporting from the DLL */ diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index e18b9fd33cd..65b26e5b81f 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -980,6 +980,9 @@ options_clauses[] = { { "interface-interval", &cfg_type_uint32, 0 }, { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, +#ifdef ISC_PLATFORM_USESIT + { "sit-secret", &cfg_type_qstring, 0 }, +#endif { "managed-keys-directory", &cfg_type_qstring, 0 }, { "match-mapped-addresses", &cfg_type_boolean, 0 }, { "max-rsa-exponent-size", &cfg_type_uint32, 0 }, @@ -1513,6 +1516,9 @@ view_clauses[] = { { "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 }, { "lame-ttl", &cfg_type_uint32, 0 }, +#ifdef ISC_PLATFORM_USESIT + { "nosit-udp-size", &cfg_type_uint32, 0 }, +#endif { "max-acache-size", &cfg_type_sizenodefault, 0 }, { "max-cache-size", &cfg_type_sizenodefault, 0 }, { "max-cache-ttl", &cfg_type_uint32, 0 }, @@ -1535,6 +1541,10 @@ view_clauses[] = { { "queryport-pool-updateinterval", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE }, { "recursion", &cfg_type_boolean, 0 }, + { "request-ixfr", &cfg_type_boolean, 0 }, +#ifdef ISC_PLATFORM_USESIT + { "request-sit", &cfg_type_boolean, 0 }, +#endif { "request-nsid", &cfg_type_boolean, 0 }, { "resolver-query-timeout", &cfg_type_uint32, 0 }, { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI }, @@ -1811,6 +1821,10 @@ server_clauses[] = { { "provide-ixfr", &cfg_type_boolean, 0 }, { "request-ixfr", &cfg_type_boolean, 0 }, { "support-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, +#ifdef ISC_PLATFORM_USESIT + { "request-sit", &cfg_type_boolean, 0 }, +#endif + { "request-nsid", &cfg_type_boolean, 0 }, { "transfers", &cfg_type_uint32, 0 }, { "transfer-format", &cfg_type_transferformat, 0 }, { "keys", &cfg_type_server_key_kludge, 0 },