mirror of https://github.com/getdnsapi/getdns.git
More conventional server DNSSEC behaviour
+ documentation of behaviour
This commit is contained in:
parent
f1b2dbeaa7
commit
7e614bc534
Binary file not shown.
Binary file not shown.
|
@ -611,6 +611,15 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
|
|||
if (!wire || !*wire || !wire_len || !msg_dict)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
do {
|
||||
char *str = gldns_wire2str_pkt((uint8_t *)*wire, *wire_len);
|
||||
DEBUG_SERVER("_getdns_wire2msg_dict_scan for a packet size: %d: %s\n",
|
||||
(int)*wire_len, str);
|
||||
free(str);
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
if (!(result = _getdns_dict_create_with_mf(mf)) ||
|
||||
!(header = _getdns_dict_create_with_mf(mf)) ||
|
||||
!(sections[SECTION_ANSWER]
|
||||
|
@ -768,11 +777,12 @@ _getdns_reply_dict2wire(
|
|||
const getdns_dict *reply, gldns_buffer *buf, int reuse_header)
|
||||
{
|
||||
uint8_t header_spc[GLDNS_HEADER_SIZE], *header;
|
||||
uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN;
|
||||
uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN, rr_type;
|
||||
size_t pkt_start, i;
|
||||
getdns_list *section;
|
||||
getdns_dict *rr_dict;
|
||||
getdns_bindata *qname;
|
||||
int remove_dnssec;
|
||||
|
||||
pkt_start = gldns_buffer_position(buf);
|
||||
if (reuse_header) {
|
||||
|
@ -814,11 +824,18 @@ _getdns_reply_dict2wire(
|
|||
buf, pkt_start+GLDNS_ARCOUNT_OFF, 0);
|
||||
}
|
||||
}
|
||||
remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0;
|
||||
DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec);
|
||||
|
||||
if (!getdns_dict_get_list(reply, "answer", §ion)) {
|
||||
for ( n = 0, i = 0
|
||||
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
|
||||
|
||||
if (!_getdns_rr_dict2wire(rr_dict, buf))
|
||||
if (remove_dnssec &&
|
||||
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
|
||||
rr_type == GETDNS_RRTYPE_RRSIG)
|
||||
continue;
|
||||
if (!_getdns_rr_dict2wire(rr_dict, buf))
|
||||
n++;
|
||||
}
|
||||
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n);
|
||||
|
@ -827,7 +844,15 @@ _getdns_reply_dict2wire(
|
|||
for ( n = 0, i = 0
|
||||
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
|
||||
|
||||
if (!_getdns_rr_dict2wire(rr_dict, buf))
|
||||
if (remove_dnssec &&
|
||||
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
|
||||
( rr_type == GETDNS_RRTYPE_RRSIG
|
||||
|| rr_type == GETDNS_RRTYPE_NSEC
|
||||
|| rr_type == GETDNS_RRTYPE_NSEC3
|
||||
|| rr_type == GETDNS_RRTYPE_DS
|
||||
))
|
||||
continue;
|
||||
if (!_getdns_rr_dict2wire(rr_dict, buf))
|
||||
n++;
|
||||
}
|
||||
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_NSCOUNT_OFF, n);
|
||||
|
@ -836,6 +861,10 @@ _getdns_reply_dict2wire(
|
|||
for ( n = 0, i = 0
|
||||
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
|
||||
|
||||
if (remove_dnssec &&
|
||||
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
|
||||
rr_type == GETDNS_RRTYPE_RRSIG)
|
||||
continue;
|
||||
if (!_getdns_rr_dict2wire(rr_dict, buf))
|
||||
n++;
|
||||
}
|
||||
|
|
|
@ -503,6 +503,72 @@ static void udp_read_cb(void *userarg)
|
|||
close(l->fd);
|
||||
l->fd = -1;
|
||||
|
||||
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
} else {
|
||||
char addrbuf[100];
|
||||
char hexbuf[4096], *hexptr;
|
||||
size_t l, i, j;
|
||||
|
||||
if (conn->remote_in.ss_family == AF_INET) {
|
||||
if (inet_ntop(AF_INET,
|
||||
&((struct sockaddr_in*)&conn->remote_in)->sin_addr,
|
||||
addrbuf, sizeof(addrbuf))) {
|
||||
|
||||
l = strlen(addrbuf);
|
||||
(void) snprintf(addrbuf + l,
|
||||
sizeof(addrbuf) - l, ":%d",
|
||||
(int)((struct sockaddr_in*)
|
||||
&conn->remote_in)->sin_port);
|
||||
} else
|
||||
(void) strncpy(
|
||||
addrbuf, "error ipv4", sizeof(addrbuf));
|
||||
|
||||
} else if (conn->remote_in.ss_family == AF_INET6) {
|
||||
addrbuf[0] = '[';
|
||||
if (inet_ntop(AF_INET6,
|
||||
&((struct sockaddr_in6*)
|
||||
&conn->remote_in)->sin6_addr,
|
||||
addrbuf, sizeof(addrbuf))) {
|
||||
|
||||
l = strlen(addrbuf);
|
||||
(void) snprintf(addrbuf + l,
|
||||
sizeof(addrbuf) - l, ":%d",
|
||||
(int)((struct sockaddr_in6*)
|
||||
&conn->remote_in)->sin6_port);
|
||||
} else
|
||||
(void) strncpy(
|
||||
addrbuf, "error ipv6", sizeof(addrbuf));
|
||||
|
||||
} else {
|
||||
(void) strncpy(
|
||||
addrbuf, "unknown address", sizeof(addrbuf));
|
||||
}
|
||||
*(hexptr = hexbuf) = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 12 == 0) {
|
||||
hexptr += snprintf(hexptr,
|
||||
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
|
||||
"\n%.4x", (int)i);
|
||||
} else if (i % 4 == 0) {
|
||||
hexptr += snprintf(hexptr,
|
||||
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
|
||||
" ");
|
||||
}
|
||||
if (hexptr - hexbuf > sizeof(hexbuf))
|
||||
break;
|
||||
hexptr += snprintf(hexptr,
|
||||
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
|
||||
" %.2x", (int)buf[i]);
|
||||
if (hexptr - hexbuf > sizeof(hexbuf))
|
||||
break;
|
||||
}
|
||||
DEBUG_SERVER("Received %d bytes from %s: %s\n",
|
||||
(int)len, addrbuf, hexbuf);
|
||||
}
|
||||
if (len == -1) {
|
||||
; /* pass */
|
||||
#endif
|
||||
|
||||
} else if ((r = getdns_wire2msg_dict(buf, len, &request_dict)))
|
||||
; /* FROMERR on input, ignore */
|
||||
|
||||
|
|
|
@ -1200,8 +1200,10 @@ typedef struct dns_msg {
|
|||
getdns_transaction_t request_id;
|
||||
getdns_dict *request;
|
||||
uint32_t rt;
|
||||
uint32_t ad_bit;
|
||||
uint32_t do_bit;
|
||||
uint32_t cd_bit;
|
||||
int has_edns0;
|
||||
} dns_msg;
|
||||
|
||||
#if defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
|
@ -1236,15 +1238,53 @@ void servfail(dns_msg *msg, getdns_dict **resp_p)
|
|||
(void) getdns_dict_set_int(*resp_p, "/header/ad", 0);
|
||||
}
|
||||
|
||||
void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
|
||||
static getdns_return_t _handle_edns0(
|
||||
getdns_dict *response, int has_edns0, uint32_t do_bit)
|
||||
{
|
||||
getdns_return_t r;
|
||||
getdns_list *additional;
|
||||
size_t len, i;
|
||||
getdns_dict *rr;
|
||||
uint32_t rr_type;
|
||||
char remove_str[100] = "/replies_tree/0/additional/";
|
||||
|
||||
if ((r = getdns_dict_set_int(
|
||||
response, "/replies_tree/0/header/do", do_bit)))
|
||||
return r;
|
||||
if (has_edns0)
|
||||
return GETDNS_RETURN_GOOD;
|
||||
if ((r = getdns_dict_get_list(response, "/replies_tree/0/additional",
|
||||
&additional)))
|
||||
return r;
|
||||
if ((r = getdns_list_get_length(additional, &len)))
|
||||
return r;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((r = getdns_list_get_dict(additional, i, &rr)))
|
||||
return r;
|
||||
if ((r = getdns_dict_get_int(rr, "type", &rr_type)))
|
||||
return r;
|
||||
if (rr_type != GETDNS_RRTYPE_OPT)
|
||||
continue;
|
||||
(void) snprintf(remove_str + 27, 60, "%d", (int)i);
|
||||
if ((r = getdns_dict_remove_name(response, remove_str)))
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static void request_cb(
|
||||
getdns_context *context, getdns_callback_type_t callback_type,
|
||||
getdns_dict *response, void *userarg, getdns_transaction_t transaction_id)
|
||||
{
|
||||
dns_msg *msg = (dns_msg *)userarg;
|
||||
uint32_t qid;
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
uint32_t n;
|
||||
uint32_t n, rcode, dnssec_status;
|
||||
|
||||
DEBUG_SERVER("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type);
|
||||
DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d,"
|
||||
" cd: %d)\n", msg, transaction_id, (int)callback_type,
|
||||
msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit);
|
||||
assert(msg);
|
||||
|
||||
#if 0
|
||||
|
@ -1263,21 +1303,36 @@ void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
|
|||
SERVFAIL("Could not copy QID", r, msg, &response);
|
||||
|
||||
else if (getdns_dict_get_int(
|
||||
response, "/replies_tree/0/header/rcode", &n))
|
||||
response, "/replies_tree/0/header/rcode", &rcode))
|
||||
SERVFAIL("No reply in replies tree", 0, msg, &response);
|
||||
|
||||
else if (msg->cd_bit != 1 && !getdns_dict_get_int(
|
||||
response, "/replies_tree/0/dnssec_status", &n)
|
||||
&& n == GETDNS_DNSSEC_BOGUS)
|
||||
/* ansers when CD or not BOGUS */
|
||||
else if (!msg->cd_bit && !getdns_dict_get_int(
|
||||
response, "/replies_tree/0/dnssec_status", &dnssec_status)
|
||||
&& dnssec_status == GETDNS_DNSSEC_BOGUS)
|
||||
SERVFAIL("DNSSEC status was bogus", 0, msg, &response);
|
||||
|
||||
else if ((r = getdns_dict_get_int(
|
||||
response, "/replies_tree/0/header/rcode", &n)))
|
||||
SERVFAIL("Could not get rcode from reply", r, msg, &response);
|
||||
|
||||
else if (n == GETDNS_RCODE_SERVFAIL)
|
||||
else if (rcode == GETDNS_RCODE_SERVFAIL)
|
||||
servfail(msg, &response);
|
||||
|
||||
/* RRsigs when DO and (CD or not BOGUS)
|
||||
* Implemented in conversion to wireformat function by checking for DO
|
||||
* bit. In recursing resolution mode we have to copy the do bit from
|
||||
* the request, because libunbound has it in the answer always.
|
||||
*/
|
||||
else if (msg->rt == GETDNS_RESOLUTION_RECURSING &&
|
||||
(r = _handle_edns0(response, msg->has_edns0, msg->do_bit)))
|
||||
SERVFAIL("Could not handle EDNS0", r, msg, &response);
|
||||
|
||||
/* AD when (DO or AD) and SECURE */
|
||||
else if ((r = getdns_dict_set_int(response,"/replies_tree/0/header/ad",
|
||||
((msg->do_bit || msg->ad_bit)
|
||||
&& ( (!msg->cd_bit && dnssec_status == GETDNS_DNSSEC_SECURE)
|
||||
|| ( msg->cd_bit && !getdns_dict_get_int(response,
|
||||
"/replies_tree/0/dnssec_status", &dnssec_status)
|
||||
&& dnssec_status == GETDNS_DNSSEC_SECURE ))) ? 1 : 0)))
|
||||
SERVFAIL("Could not set AD bit", r, msg, &response);
|
||||
|
||||
else if (msg->rt == GETDNS_RESOLUTION_STUB)
|
||||
; /* following checks are for RESOLUTION_RECURSING only */
|
||||
|
||||
|
@ -1324,6 +1379,10 @@ static void incoming_request_handler(getdns_context *context,
|
|||
getdns_dict *qext = NULL;
|
||||
dns_msg *msg = NULL;
|
||||
getdns_dict *response = NULL;
|
||||
size_t i, len;
|
||||
getdns_list *additional;
|
||||
getdns_dict *rr;
|
||||
uint32_t rr_type;
|
||||
|
||||
if (!query_extensions_spc &&
|
||||
!(query_extensions_spc = getdns_dict_create()))
|
||||
|
@ -1345,10 +1404,26 @@ static void incoming_request_handler(getdns_context *context,
|
|||
n = 0;
|
||||
msg->request_id = request_id;
|
||||
msg->request = request;
|
||||
msg->do_bit = msg->cd_bit = 0;
|
||||
msg->rt = GETDNS_RESOLUTION_STUB;
|
||||
(void) getdns_dict_get_int(request, "/additional/0/do", &msg->do_bit);
|
||||
msg->ad_bit = msg->do_bit = msg->cd_bit = 0;
|
||||
msg->has_edns0 = 0;
|
||||
msg->rt = GETDNS_RESOLUTION_RECURSING;
|
||||
(void) getdns_dict_get_int(request, "/header/ad", &msg->ad_bit);
|
||||
(void) getdns_dict_get_int(request, "/header/cd", &msg->cd_bit);
|
||||
if (!getdns_dict_get_list(request, "additional", &additional)) {
|
||||
if (getdns_list_get_length(additional, &len))
|
||||
len = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (getdns_list_get_dict(additional, i, &rr))
|
||||
break;
|
||||
if (getdns_dict_get_int(rr, "type", &rr_type))
|
||||
break;
|
||||
if (rr_type != GETDNS_RRTYPE_OPT)
|
||||
continue;
|
||||
msg->has_edns0 = 1;
|
||||
(void) getdns_dict_get_int(rr, "do", &msg->do_bit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((r = getdns_context_get_resolution_type(context, &msg->rt)))
|
||||
fprintf(stderr, "Could get resolution type from context: %s\n",
|
||||
getdns_get_errorstr_by_id(r));
|
||||
|
@ -1359,15 +1434,10 @@ static void incoming_request_handler(getdns_context *context,
|
|||
if (!getdns_dict_get_dict(request, "header", &header))
|
||||
(void)getdns_dict_set_dict(qext, "header", header);
|
||||
|
||||
} else if (getdns_dict_get_int(extensions,"dnssec_return_status",&n) ||
|
||||
n == GETDNS_EXTENSION_FALSE)
|
||||
(void)getdns_dict_set_int(qext, "dnssec_return_status",
|
||||
msg->do_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE);
|
||||
|
||||
if (!getdns_dict_get_int(qext, "dnssec_return_status", &n) &&
|
||||
n == GETDNS_EXTENSION_TRUE)
|
||||
(void) getdns_dict_set_int(qext, "dnssec_return_all_statuses",
|
||||
msg->cd_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE);
|
||||
}
|
||||
if (msg->cd_bit)
|
||||
getdns_dict_set_int(qext, "dnssec_return_all_statuses",
|
||||
GETDNS_EXTENSION_TRUE);
|
||||
|
||||
if (!getdns_dict_get_int(request, "/additional/0/extended_rcode",&n))
|
||||
(void)getdns_dict_set_int(
|
||||
|
@ -1431,6 +1501,16 @@ error:
|
|||
if (qname_str)
|
||||
free(qname_str);
|
||||
servfail(msg, &response);
|
||||
#if defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
do {
|
||||
char *request_str = getdns_pretty_print_dict(request);
|
||||
char *response_str = getdns_pretty_print_dict(response);
|
||||
DEBUG_SERVER("request error, request: %s\n, response: %s\n"
|
||||
, request_str, response_str);
|
||||
free(response_str);
|
||||
free(request_str);
|
||||
} while(0);
|
||||
#endif
|
||||
if (!response)
|
||||
/* No response, no reply */
|
||||
_getdns_cancel_reply(context, request_id);
|
||||
|
|
Loading…
Reference in New Issue