diff --git a/CHANGES b/CHANGES index 73db27e932..b2dbc0cccf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5154. [bug] dig: process_opt could be called twice on the same + message leading to a assertion failure. [GL #860] + 5153. [func] Zone transfer statistics (size, number of records, and number of messages) are now logged for outgoing transfers as well as incoming ones. [GL #513] diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index f3904d7263..9249ebd021 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -3422,7 +3422,7 @@ process_cookie(dig_lookup_t *l, dns_message_t *msg, } INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); - if (optlen >= len && optlen >= 8U) { + if (len >= 8 && optlen >= 8U) { if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { msg->cc_ok = 1; } else { @@ -3509,6 +3509,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { dig_lookup_t *n, *l; bool docancel = false; bool match = true; + bool done_process_opt = false; unsigned int parseflags; dns_messageid_t id; unsigned int msgflags; @@ -3802,6 +3803,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { UNLOCK_LOOKUP; return; } + done_process_opt = true; } if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) @@ -3891,13 +3893,17 @@ recv_done(isc_task_t *task, isc_event_t *event) { } } - if (l->cookie != NULL) { - if (msg->opt == NULL) - printf(";; expected opt record in response\n"); - else + if (!done_process_opt) { + if (l->cookie != NULL) { + if (msg->opt == NULL) { + printf(";; expected opt record in response\n"); + } else { + process_opt(l, msg); + } + } else if (l->sendcookie && msg->opt != NULL) { process_opt(l, msg); - } else if (l->sendcookie && msg->opt != NULL) - process_opt(l, msg); + } + } if (!l->doing_xfr || l->xfr_q == query) { if (msg->rcode == dns_rcode_nxdomain && (l->origin != NULL || l->need_search)) { diff --git a/bin/tests/system/cookie/tests.sh b/bin/tests/system/cookie/tests.sh index 598a9b9ab2..0c4d25a77a 100755 --- a/bin/tests/system/cookie/tests.sh +++ b/bin/tests/system/cookie/tests.sh @@ -184,6 +184,30 @@ if [ $linecount != 2 ]; then ret=1; fi if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo_i "send undersized cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=000000 soa @10.53.0.1 > dig.out.test$n || ret=1 +grep "status: FORMERR" 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 "send oversized for named cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.1 > dig.out.test$n || ret=1 +grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n > /dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "send oversized for named cookie with server requiring a good cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.3 > dig.out.test$n || ret=1 +grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n > /dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + # # Test shared cookie-secret support. #