From 7e614bc534b2c69ae70dbf7a93d4441b7b42da46 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jul 2016 15:13:40 +0200 Subject: [PATCH] More conventional server DNSSEC behaviour + documentation of behaviour --- project-doc/getdns_query-deamon-behaviour.ods | Bin 0 -> 17609 bytes project-doc/getdns_query-deamon-behaviour.pdf | Bin 0 -> 13995 bytes src/convert.c | 35 ++++- .../getdns_context_set_listen_addresses.c | 66 +++++++++ src/test/getdns_query.c | 128 ++++++++++++++---- 5 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 project-doc/getdns_query-deamon-behaviour.ods create mode 100644 project-doc/getdns_query-deamon-behaviour.pdf diff --git a/project-doc/getdns_query-deamon-behaviour.ods b/project-doc/getdns_query-deamon-behaviour.ods new file mode 100644 index 0000000000000000000000000000000000000000..041cebc754bfe60ac255409c9d2c70f5e6687f21 GIT binary patch literal 17609 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 N4ML`+l~e*F|3AzLS^@w7 literal 0 HcmV?d00001 diff --git a/src/convert.c b/src/convert.c index 2539d7bd..5eb1a513 100644 --- a/src/convert.c +++ b/src/convert.c @@ -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++; } diff --git a/src/test/getdns_context_set_listen_addresses.c b/src/test/getdns_context_set_listen_addresses.c index eeeac3ad..fcfe9057 100644 --- a/src/test/getdns_context_set_listen_addresses.c +++ b/src/test/getdns_context_set_listen_addresses.c @@ -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 */ diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 09184e6d..54464bcd 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -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);