*control = acl_allow_snoop;
else if(strcmp(str, "allow_setrd") == 0)
*control = acl_allow_setrd;
- else if (strcmp(s2, "allow_cookie") == 0)
+ else if (strcmp(str, "allow_cookie") == 0)
*control = acl_allow_cookie;
else {
log_err("access control type %s unknown", str);
struct query_info* lookup_qinfo = &qinfo;
struct query_info qinfo_tmp; /* placeholder for lookup_qinfo */
struct respip_client_info* cinfo = NULL, cinfo_tmp;
- int valid_cookie = 0;
memset(&qinfo, 0, sizeof(qinfo));
+ memset(&edns, 0, sizeof(edns));
+ edns.udp_size = 512;
if((error != NETEVENT_NOERROR && error != NETEVENT_DONE)|| !repinfo) {
/* some bad tcp query DNS formats give these error calls */
}
goto send_reply;
}
- if((ret=parse_edns_from_query_pkt(c->buffer, &edns, worker->env.cfg, c,
- worker->scratchpad)) != 0) {
+ if((ret=parse_edns_from_query_pkt(
+ c->buffer, &edns, worker->env.cfg, c, repinfo,
+ (worker->env.now ? *worker->env.now : time(NULL)),
+ worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
regional_free_all(worker->scratchpad);
goto send_reply;
}
- if(!edns.edns_present) {
- if(c->type == comm_udp && acl == acl_allow_cookie) {
- verbose(VERB_ALGO, "worker request: "
- "need cookie or stateful transport");
- log_addr(VERB_ALGO, "from",
- &repinfo->addr, repinfo->addrlen);
- LDNS_QR_SET(sldns_buffer_begin(c->buffer));
- LDNS_TC_SET(sldns_buffer_begin(c->buffer));
- LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
- LDNS_RCODE_REFUSED);
- sldns_buffer_set_position(c->buffer,
- LDNS_HEADER_SIZE);
- sldns_buffer_write_at(c->buffer, 4,
- (uint8_t*)"\0\0\0\0\0\0\0\0", 8);
- sldns_buffer_flip(c->buffer);
- regional_free_all(worker->scratchpad);
- goto send_reply;
- }
+ if(edns.edns_present && edns.edns_version != 0) {
+ edns.opt_list_in = NULL;
+ edns.opt_list_out = NULL;
+ edns.opt_list_inplace_cb_out = NULL;
+ edns.padding_block_size = 0;
+ edns.cookie_present = 0;
+ edns.cookie_valid = 0;
+ verbose(VERB_ALGO, "query with bad edns version.");
+ log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
+ error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo,
+ *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2), &edns);
+ regional_free_all(worker->scratchpad);
+ goto send_reply;
+ }
+ if(edns.udp_size < NORMAL_UDP_SIZE &&
+ worker->daemon->cfg->harden_short_bufsize) {
+ verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
+ (int)edns.udp_size);
+ log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
+ edns.udp_size = NORMAL_UDP_SIZE;
+ }
+ /* "if, else if" sequence below deals with downstream DNS Cookies */
+ if (acl != acl_allow_cookie)
+ ; /* pass; No cookie downstream processing whatsoever */
+
+ else if (edns.cookie_valid)
+ ; /* pass; Valid cookie is good! */
+
+ else if (c->type != comm_udp)
+ ; /* pass; Stateful transport */
+
+ else if (edns.cookie_present) {
+ /* Cookie present, but not valid: Cookie was bad! */
+ error_encode(c->buffer,
+ LDNS_EXT_RCODE_BADCOOKIE, &qinfo,
+ *(uint16_t*)(void *)
+ sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2),
+ &edns);
+ regional_free_all(worker->scratchpad);
+ goto send_reply;
} else {
- struct edns_option* edns_opt;
-
- if(edns.edns_version != 0) {
- edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
- edns.edns_version = EDNS_ADVERTISED_VERSION;
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- edns.bits &= EDNS_DO;
- edns.opt_list_in = NULL;
- edns.opt_list_out = NULL;
- edns.opt_list_inplace_cb_out = NULL;
- edns.padding_block_size = 0;
- verbose(VERB_ALGO, "query with bad edns version.");
- log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
- error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
- *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2), NULL);
- if(sldns_buffer_capacity(c->buffer) >=
- sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
- attach_edns_record(c->buffer, &edns);
- regional_free_all(worker->scratchpad);
- goto send_reply;
- }
- if(edns.udp_size < NORMAL_UDP_SIZE &&
- worker->daemon->cfg->harden_short_bufsize) {
- verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
- (int)edns.udp_size);
- log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
- edns.udp_size = NORMAL_UDP_SIZE;
- }
- if(c->type == comm_udp) {
- /* Cookies only on UDP */
-
- if(!worker->daemon->cfg->do_answer_cookie)
- ; /* pass; No cookie processing whatsoever */
-
- else if(!(edns_opt = edns_opt_list_find(
- edns.opt_list, LDNS_EDNS_COOKIE))) {
- ; /* pass; No cookie option present */
-
- } else if(edns_opt->opt_len != 8 &&
- ( edns_opt->opt_len < 16
- || edns_opt->opt_len > 40)) {
- edns.ext_rcode = 0;
- edns.edns_version = EDNS_ADVERTISED_VERSION;
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- edns.bits &= EDNS_DO;
- edns.opt_list = NULL;
- verbose(VERB_ALGO, "worker request: "
- "badly formatted cookie");
- log_addr(VERB_CLIENT, "from",
- &repinfo->addr, repinfo->addrlen);
- error_encode(c->buffer, LDNS_RCODE_FORMERR,
- &qinfo, *(uint16_t*)(void *)
- sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2),
- NULL);
- if(sldns_buffer_capacity(c->buffer) >=
- sldns_buffer_limit(c->buffer)
- + calc_edns_field_size(&edns))
- attach_edns_record(c->buffer, &edns);
- regional_free_all(worker->scratchpad);
- goto send_reply;
-
- } else if (edns_cookie_validate(worker->env.cfg,
- repinfo, edns_opt, *worker->env.now)) {
- valid_cookie = 1;
-
- } else if (acl == acl_allow_cookie) {
- struct edns_data edns_bak = edns;
- int rcode;
-
- /* With invalid or just client Cookie
- * reply with BADCOOKIE + server cookie
- */
- edns.ext_rcode = 0;
- edns.edns_version = EDNS_ADVERTISED_VERSION;
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- edns.bits &= EDNS_DO;
- edns.opt_list = NULL;
- if (apply_edns_options(&edns, &edns_bak,
- worker->env.cfg, c,
- repinfo,
- *worker->env.now,
- worker->scratchpad)) {
- edns.ext_rcode = 1;
- rcode = LDNS_EXT_RCODE_BADCOOKIE & 0xF;
- } else
- rcode = LDNS_RCODE_SERVFAIL;
- error_encode(c->buffer, rcode, &qinfo,
- *(uint16_t*)(void *)
- sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2),
- NULL);
- if(sldns_buffer_capacity(c->buffer) >=
- sldns_buffer_limit(c->buffer)
- + calc_edns_field_size(&edns))
- attach_edns_record(c->buffer, &edns);
- regional_free_all(worker->scratchpad);
- goto send_reply;
- }
- if (acl == acl_allow_cookie && !valid_cookie) {
- verbose(VERB_ALGO, "worker request: "
- "need cookie or stateful transport");
- log_addr(VERB_ALGO, "from",
- &repinfo->addr, repinfo->addrlen);
- LDNS_QR_SET(sldns_buffer_begin(c->buffer));
- LDNS_TC_SET(sldns_buffer_begin(c->buffer));
- LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
- LDNS_RCODE_REFUSED);
- sldns_buffer_set_position(c->buffer,
- LDNS_HEADER_SIZE);
- sldns_buffer_write_at(c->buffer, 4,
- (uint8_t*)"\0\0\0\0\0\0\0\0", 8);
- sldns_buffer_flip(c->buffer);
- regional_free_all(worker->scratchpad);
- goto send_reply;
- }
-
- } else { /* if(c->type == comm_udp) */
- edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE);
- if(edns_opt && edns_opt->opt_len > 0) {
- edns.ext_rcode = 0;
- edns.edns_version = EDNS_ADVERTISED_VERSION;
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- edns.bits &= EDNS_DO;
- edns.opt_list = NULL;
- verbose(VERB_ALGO, "query with bad edns keepalive.");
- log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
- error_encode(c->buffer, LDNS_RCODE_FORMERR, &qinfo,
- *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2), NULL);
- if(sldns_buffer_capacity(c->buffer) >=
- sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
- attach_edns_record(c->buffer, &edns);
- regional_free_all(worker->scratchpad);
- goto send_reply;
- }
- }
+ /* Cookie requered, but no cookie present on UDP */
+ verbose(VERB_ALGO, "worker request: "
+ "need cookie or stateful transport");
+ log_addr(VERB_ALGO, "from",
+ &repinfo->addr, repinfo->addrlen);
+ EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
+ worker->scratchpad, LDNS_EDE_OTHER,
+ "DNS Cookie needed for UDP replies");
+ error_encode(c->buffer,
+ LDNS_RCODE_REFUSED, &qinfo,
+ *(uint16_t*)(void *)
+ sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2),
+ &edns);
+ LDNS_TC_SET(sldns_buffer_begin(c->buffer));
+ regional_free_all(worker->scratchpad);
+ goto send_reply;
}
if(edns.udp_size > worker->daemon->cfg->max_udp_size &&
c->type == comm_udp) {
Enable to answer to requests containig DNS Cookies as specified in RFC7873.
Default is yes.
.TP 5
-.B cookie\-secret: \fI<128, 192 or 256 bit hex string>
+.B cookie\-secret: \fI<128 bit hex string>
Server's in an Anycast deployment need to be able to verify each other's
Server Cookies. For this they need to share the secret used to construct
and verify the Server Cookies.
useful when you want immediate changes to be visible.
.SS "Authority Zone Options"
.LP
-Authority zones are configured with \fBauth\-zone:\fR, and each one must have a
-\fBname:\fR. There can be multiple ones, by listing multiple auth\-zone
-clauses, each with a different name, pertaining to that part of the namespace.
+Authority zones are configured with \fBauth\-zone:\fR, and each one must
+have a \fBname:\fR. There can be multiple ones, by listing multiple auth\-zone clauses, each with a different name, pertaining to that part of the namespace.
The authority zone with the name closest to the name looked up is used.
Authority zones are processed after \fBlocal\-zones\fR and before
cache (\fBfor\-downstream:\fR \fIyes\fR), and when used in this manner
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
+ edns->cookie_present = 0;
+ edns->cookie_valid = 0;
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
edns->udp_size = (uint16_t)sldns_buffer_capacity(
w->back->udp_buff);
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
+ edns.cookie_present = 0;
+ edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
+ edns.cookie_present = 0;
+ edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
if(dnssec)
edns.bits = EDNS_DO;
edns.padding_block_size = 0;
+ edns.cookie_present = 0;
+ edns.cookie_valid = 0;
edns.opt_list_in = NULL;
edns.opt_list_out = per_upstream_opt_list;
edns.opt_list_inplace_cb_out = NULL;
sldns_buffer_clear(buf);
sldns_buffer_write(buf, &qid, sizeof(uint16_t));
- flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
+ flags = (uint16_t)(BIT_QR | BIT_RA | (r & 0xF)); /* QR and retcode*/
flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
sldns_buffer_write_u16(buf, flags);
if(qinfo) flags = 1;
size_t edns_field_size = calc_edns_field_size(&es);
es.edns_version = EDNS_ADVERTISED_VERSION;
es.udp_size = EDNS_ADVERTISED_SIZE;
- es.ext_rcode = 0;
+ es.ext_rcode = r >= 0x10 ? 1 : 0;
es.bits &= EDNS_DO;
if(sldns_buffer_limit(buf) + edns_field_size > edns->udp_size)
return;
data, region);
}
+int siphash(const uint8_t *in, const size_t inlen,
+ const uint8_t *k, uint8_t *out, const size_t outlen);
+
+/** RFC 1982 comparison, uses unsigned integers, and tries to avoid
+ * compiler optimization (eg. by avoiding a-b<0 comparisons),
+ * this routine matches compare_serial(), for SOA serial number checks */
+static int
+compare_1982(uint32_t a, uint32_t b)
+{
+ /* for 32 bit values */
+ const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
+
+ if (a == b) {
+ return 0;
+ } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+/** if we know that b is larger than a, return the difference between them,
+ * that is the distance between them. in RFC1982 arith */
+static uint32_t
+subtract_1982(uint32_t a, uint32_t b)
+{
+ /* for 32 bit values */
+ const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
+
+ if(a == b)
+ return 0;
+ if(a < b && b - a < cutoff) {
+ return b-a;
+ }
+ if(a > b && a - b > cutoff) {
+ return ((uint32_t)0xffffffff) - (a-b-1);
+ }
+ /* wrong case, b smaller than a */
+ return 0;
+}
+
+
+static uint8_t *
+cookie_hash(uint8_t *hash, uint8_t *buf,
+ struct sockaddr_storage *addr, uint8_t *secret)
+{
+ if (addr->ss_family == AF_INET6) {
+ memcpy(buf+16, &((struct sockaddr_in6 *)addr)->sin6_addr, 16);
+ siphash(buf, 32, secret, hash, 8);
+ } else {
+ memcpy(buf+16, &((struct sockaddr_in *)addr)->sin_addr, 4);
+ siphash(buf, 20, secret, hash, 8);
+ }
+ return hash;
+}
+
/** parse EDNS options from EDNS wireformat rdata */
static int
parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
- struct regional* region)
+ struct comm_reply* repinfo, uint32_t now, struct regional* region)
{
/* To respond with a Keepalive option, the client connection must have
* received one message with a TCP Keepalive EDNS option, and that
while(rdata_len >= 4) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
+ uint8_t server_cookie[40], hash[8];
+ uint32_t cookie_time, subt_1982;
+ int comp_1982;
+
rdata_ptr += 4;
rdata_len -= 4;
if(opt_len > rdata_len)
edns->padding_block_size = cfg->pad_responses_block_size;
break;
+ case LDNS_EDNS_COOKIE:
+ if(!cfg || !cfg->do_answer_cookie)
+ break;
+ if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) {
+ verbose(VERB_ALGO, "worker request: "
+ "badly formatted cookie");
+ return LDNS_RCODE_FORMERR;
+ }
+ edns->cookie_present = 1;
+
+ /* Copy client cookie, version and timestamp for
+ * validation and creation purposes.
+ */
+ memcpy(server_cookie, rdata_ptr, 16);
+
+ /* In the "if, if else" block below, we validate a
+ * RFC9018 cookie. If it doesn't match the recipe, or
+ * if it doesn't validate, or if the cookie is too old
+ * (< 30 min), a new cookie is generated.
+ */
+ if (opt_len != 24)
+ ; /* RFC9018 cookies are 24 bytes long */
+
+ else if (cfg->cookie_secret_len != 16)
+ ; /* RFC9018 cookies have 16 byte secrets */
+
+ else if (rdata_ptr[8] != 1)
+ ; /* RFC9018 cookies are cookie version 1 */
+
+ else if ((comp_1982 = compare_1982(now,
+ (cookie_time = sldns_read_uint32(rdata_ptr + 12)))) > 0
+ && (subt_1982 = subtract_1982(cookie_time, now)) > 3600)
+ ; /* Cookie is older than 1 hour
+ * (see RFC9018 Section 4.3.)
+ */
+
+ else if (comp_1982 <= 0
+ && subtract_1982(now, cookie_time) > 300)
+ ; /* Cookie time is more than 5 minutes in the
+ * future. (see RFC9018 Section 4.3.)
+ */
+
+ else if (memcmp( cookie_hash( hash, server_cookie
+ , &repinfo->addr
+ , cfg->cookie_secret)
+ , rdata_ptr + 16 , 8 ) == 0) {
+
+ /* Cookie is valid! */
+ edns->cookie_valid = 1;
+ if (comp_1982 > 0 && subt_1982 > 1800)
+ ; /* But older than 30 minutes,
+ * so create a new one anyway */
+
+ else if (!edns_opt_list_append( /* Reuse cookie */
+ &edns->opt_list_out, LDNS_EDNS_COOKIE, opt_len,
+ rdata_ptr, region)) {
+ log_err("out of memory");
+ return LDNS_RCODE_SERVFAIL;
+ } else
+ /* Cookie to be reused added to
+ * outgoing options. Done!
+ */
+ break;
+ }
+ /* Add a new server cookie to outgoing cookies */
+ server_cookie[ 8] = 1; /* Version */
+ server_cookie[ 9] = 0; /* Reserved */
+ server_cookie[10] = 0; /* Reserved */
+ server_cookie[11] = 0; /* Reserved */
+ sldns_write_uint32(server_cookie + 12, now);
+ cookie_hash( hash, server_cookie
+ , &repinfo->addr, cfg->cookie_secret);
+ memcpy(server_cookie + 16, hash, 8);
+ if (!edns_opt_list_append( &edns->opt_list_out
+ , LDNS_EDNS_COOKIE
+ , 24, server_cookie, region)) {
+ log_err("out of memory");
+ return LDNS_RCODE_SERVFAIL;
+ }
+ break;
default:
break;
}
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
+ edns->cookie_present = 0;
+ edns->cookie_valid = 0;
/* take the options */
rdata_len = found->rr_first->size-2;
int
parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns,
- struct config_file* cfg, struct comm_point* c, struct regional* region)
+ struct config_file* cfg, struct comm_point* c,
+ struct comm_reply* repinfo, time_t now, struct regional* region)
{
size_t rdata_len;
uint8_t* rdata_ptr;
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
+ edns->cookie_present = 0;
+ edns->cookie_valid = 0;
/* take the options */
rdata_len = sldns_buffer_read_u16(pkt);
rdata_ptr = sldns_buffer_current(pkt);
/* ignore rrsigs */
return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg,
- c, region);
+ c, repinfo, now, region);
}
void
struct edns_option;
struct config_file;
struct comm_point;
+struct comm_reply;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
* region.
*/
struct edns_data {
- /** if EDNS OPT record was present */
- int edns_present;
/** Extended RCODE */
uint8_t ext_rcode;
/** The EDNS version number */
struct edns_option* opt_list_inplace_cb_out;
/** block size to pad */
uint16_t padding_block_size;
-};
+ /** if EDNS OPT record was present */
+ unsigned int edns_present : 1;
+ /** if a cookie was present */
+ unsigned int cookie_present : 1;
+ /** if the cookie validated */
+ unsigned int cookie_valid : 1;
+};
/**
* EDNS option
* RCODE formerr if OPT is badly formatted and so on.
*/
int parse_edns_from_query_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
- struct config_file* cfg, struct comm_point* c, struct regional* region);
+ struct config_file* cfg, struct comm_point* c,
+ struct comm_reply* repinfo, time_t now, struct regional* region);
/**
* Calculate hash value for rrset in packet.
#include "util/regional.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
-#include "sldns/sbuffer.h"
-
-#ifdef HAVE_SSL
-#include <openssl/opensslv.h>
-#include <openssl/evp.h>
-#endif
struct edns_strings* edns_strings_create(void)
{
return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
}
-int siphash(const uint8_t *in, const size_t inlen,
- const uint8_t *k, uint8_t *out, const size_t outlen);
-
-/** RFC 1982 comparison, uses unsigned integers, and tries to avoid
- * compiler optimization (eg. by avoiding a-b<0 comparisons),
- * this routine matches compare_serial(), for SOA serial number checks */
-static int
-compare_1982(uint32_t a, uint32_t b)
-{
- /* for 32 bit values */
- const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
-
- if (a == b) {
- return 0;
- } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
- return -1;
- } else {
- return 1;
- }
-}
-
-/** if we know that b is larger than a, return the difference between them,
- * that is the distance between them. in RFC1982 arith */
-static uint32_t
-subtract_1982(uint32_t a, uint32_t b)
-{
- /* for 32 bit values */
- const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
-
- if(a == b)
- return 0;
- if(a < b && b - a < cutoff) {
- return b-a;
- }
- if(a > b && a - b > cutoff) {
- return ((uint32_t)0xffffffff) - (a-b-1);
- }
- /* wrong case, b smaller than a */
- return 0;
-}
-
-
-int edns_cookie_validate(struct config_file* cfg, struct comm_reply* repinfo,
- struct edns_option* cookie_opt, time_t now)
-{
- uint8_t hash[8], data2hash[40];
- uint32_t cookie_time, now_uint32 = now;
-
- /* We support only draft-sury-toorop-dns-cookies-algorithms
- * sized cookies
- */
- if(cookie_opt->opt_len != 24)
- return 0;
-
- if(cookie_opt->opt_data[8] != 1)
- return 0;
-
- cookie_time = sldns_read_uint32(cookie_opt->opt_data + 12);
-
- if(compare_1982(now_uint32, cookie_time) > 0) {
- if (subtract_1982(cookie_time, now_uint32) > 3600)
- return 0; /* Not older than 1 hour */
-
- } else if (subtract_1982(now_uint32, cookie_time) > 300)
- /* ignore cookies > 5 minutes in future */
- return 0;
-
- if (cfg->cookie_secret_len != 16)
- return 0;
-
- memcpy(data2hash, cookie_opt->opt_data, 16);
- if (repinfo->addr.ss_family == AF_INET6) {
- memcpy( data2hash + 16, &((struct sockaddr_in6 *)
- &repinfo->addr)->sin6_addr, 16);
- siphash(data2hash, 32, cfg->cookie_secret, hash, 8);
- } else {
- memcpy( data2hash + 16, &((struct sockaddr_in *)
- &repinfo->addr)->sin_addr, 4);
- siphash(data2hash, 20, cfg->cookie_secret, hash, 8);
- }
- return memcmp(cookie_opt->opt_data + 16, hash, 8) == 0;
-}
-
-static int edns_cookie(struct edns_data* edns_out, struct edns_data* edns_in,
- struct config_file* cfg, struct comm_point* c,
- struct comm_reply *repinfo, time_t now,
- struct regional* region)
-{
- struct edns_option *opt;
-
- if(c->type != comm_udp)
- return 1;
-
- if(!cfg->do_answer_cookie)
- return 1;
-
- opt = edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_COOKIE);
- if (opt && opt->opt_len >= 8) {
- uint8_t data_out[40], hash[8];
-
- log_assert(cfg->cookie_secret_len >= 16);
-
- (void)memcpy(data_out, opt->opt_data, 8);
- data_out[ 8] = 1; /* Version */
- data_out[ 9] = 0; /* Reserved */
- data_out[10] = 0; /* Reserved */
- data_out[11] = 0; /* Reserved */
- sldns_write_uint32(data_out + 12, time(NULL));
- if (repinfo->addr.ss_family == AF_INET6) {
- memcpy( data_out + 16, &((struct sockaddr_in6 *)
- &repinfo->addr)->sin6_addr, 16);
- siphash(data_out, 32, cfg->cookie_secret, hash, 8);
- } else {
- memcpy( data_out + 16, &((struct sockaddr_in *)
- &repinfo->addr)->sin_addr, 4);
- siphash(data_out, 20, cfg->cookie_secret, hash, 8);
- }
- memcpy(data_out + 16, hash, 8);
- if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_COOKIE,
- 24, data_out, region))
- return 0;
- }
- return 1;
-}
-
#include "util/storage/dnstree.h"
-struct edns_option;
struct edns_data;
struct config_file;
struct comm_point;
struct regional;
-struct comm_reply;
-/**
- * Validate the EDNS Server cookie.
- *
- * @param cfg: configuration.
- * @param repinfo: struct containing the address of the querier.
- * @param cookie_opt: comm channel.
- * @param now: current time.
- * @return 1 on a valid server cookie, otherwise 0.
- */
-int edns_cookie_validate(struct config_file* cfg, struct comm_reply* repinfo,
- struct edns_option* cookie_opt, time_t now) ;
/**
* Structure containing all EDNS strings.
*/
#define MAX_ADDR_STRLEN 128 /* characters */
/** default value for EDNS ADVERTISED size */
uint16_t EDNS_ADVERTISED_SIZE = 4096;
-/** default value of padding block size with encrypted queries (RFC8467) */
-uint16_t EDNS_PADDING_QUERY_BLOCK_SIZE = 128;
-/** default value of padding block size with encrypted responses (RFC8467) */
-uint16_t EDNS_PADDING_RESPONSE_BLOCK_SIZE = 468;
/** minimal responses when positive answer: default is no */
int MINIMAL_RESPONSES = 0;
#define INET_SIZE 4
/** byte size of ip6 address */
#define INET6_SIZE 16
-/** block size with which to pad encrypted queries */
-extern uint16_t EDNS_PADDING_QUERY_BLOCK_SIZE;
-/** block size with which to pad encrypted responses */
-extern uint16_t EDNS_PADDING_RESPONSE_BLOCK_SIZE;
/** DNSKEY zone sign key flag */
#define DNSKEY_BIT_ZSK 0x0100
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
+ edns.cookie_present = 0;
+ edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;