Commit 10c53d28 authored by Mark Andrews's avatar Mark Andrews

Recognise EDNS Client Tag and EDNS Server Tag

(cherry picked from commit ee7cf180)
parent ac9286b7
Pipeline #14281 passed with stages
in 13 minutes and 38 seconds
5231. [protocol] Add support for displaying CLIENT-TAG and SERVER-TAG.
[GL #960]
5229. [protocol] Enforce known SSHFP fingerprint lengths. [GL #852]
5228. [cleanup] If trusted-keys and managed-keys are configured
......
......@@ -1682,6 +1682,8 @@ dig_ednsoptname_t optnames[] = {
{ 12, "PAD" }, /* shorthand */
{ 13, "CHAIN" }, /* RFC 7901 */
{ 14, "KEY-TAG" }, /* RFC 8145 */
{ 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */
{ 26946, "DEVICEID" }, /* Brian Hartvigsen */
};
......
......@@ -483,6 +483,54 @@ ret=0
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that dig processes +ednsopt=client-tag:value ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=client-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; CLIENT-TAG: 1$" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that FORMERR is returned for a too short client-tag ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=client-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that FORMERR is returned for a too long client-tag ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=client-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that dig processes +ednsopt=server-tag:value ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=server-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; SERVER-TAG: 1$" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that FORMERR is returned for a too short server-tag ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=server-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that FORMERR is returned for a too long server-tag ($n)"
$DIG $DIGOPTS @10.53.0.3 +ednsopt=server-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that dig handles malformed option '+ednsopt=:' gracefully ($n)"
ret=0
......
......@@ -105,6 +105,8 @@
#define DNS_OPT_COOKIE 10 /*%< COOKIE opt code */
#define DNS_OPT_PAD 12 /*%< PAD opt code */
#define DNS_OPT_KEY_TAG 14 /*%< Key tag opt code */
#define DNS_OPT_CLIENT_TAG 16 /*%< Client tag opt code */
#define DNS_OPT_SERVER_TAG 17 /*%< Server tag opt code */
/*%< Experimental options [65001...65534] as per RFC6891 */
......
......@@ -3584,6 +3584,30 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg,
ADD_STRING(target, "\n");
continue;
}
} else if (optcode == DNS_OPT_CLIENT_TAG) {
uint16_t id;
INDENT(style);
ADD_STRING(target, "CLIENT-TAG");
if (optlen == 2U) {
id = isc_buffer_getuint16(&optbuf);
snprintf(buf, sizeof(buf), ": %u\n",
id);
ADD_STRING(target, buf);
optlen -= 2;
continue;
}
} else if (optcode == DNS_OPT_SERVER_TAG) {
uint16_t id;
INDENT(style);
ADD_STRING(target, "SERVER-TAG");
if (optlen == 2U) {
id = isc_buffer_getuint16(&optbuf);
snprintf(buf, sizeof(buf), ": %u\n",
id);
ADD_STRING(target, buf);
optlen -= 2;
continue;
}
} else {
INDENT(style);
ADD_STRING(target, "OPT: ");
......@@ -3831,6 +3855,28 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ADD_STRING(target, "\n");
continue;
}
} else if (optcode == DNS_OPT_CLIENT_TAG) {
uint16_t id;
ADD_STRING(target, "; CLIENT-TAG");
if (optlen == 2U) {
id = isc_buffer_getuint16(&optbuf);
snprintf(buf, sizeof(buf), ": %u\n",
id);
ADD_STRING(target, buf);
optlen -= 2;
continue;
}
} else if (optcode == DNS_OPT_SERVER_TAG) {
uint16_t id;
ADD_STRING(target, "; SERVER-TAG");
if (optlen == 2U) {
id = isc_buffer_getuint16(&optbuf);
snprintf(buf, sizeof(buf), ": %u\n",
id);
ADD_STRING(target, buf);
optlen -= 2;
continue;
}
} else {
ADD_STRING(target, "; OPT=");
snprintf(buf, sizeof(buf), "%u", optcode);
......
......@@ -99,19 +99,22 @@ fromwire_opt(ARGS_FROMWIRE) {
UNUSED(options);
isc_buffer_activeregion(source, &sregion);
if (sregion.length == 0)
if (sregion.length == 0) {
return (ISC_R_SUCCESS);
}
total = 0;
while (sregion.length != 0) {
if (sregion.length < 4)
if (sregion.length < 4) {
return (ISC_R_UNEXPECTEDEND);
}
opt = uint16_fromregion(&sregion);
isc_region_consume(&sregion, 2);
length = uint16_fromregion(&sregion);
isc_region_consume(&sregion, 2);
total += 4;
if (sregion.length < length)
if (sregion.length < length) {
return (ISC_R_UNEXPECTEDEND);
}
switch (opt) {
case DNS_OPT_CLIENT_SUBNET: {
uint16_t family;
......@@ -119,8 +122,9 @@ fromwire_opt(ARGS_FROMWIRE) {
uint8_t scope;
uint8_t addrbytes;
if (length < 4)
if (length < 4) {
return (DNS_R_OPTERR);
}
family = uint16_fromregion(&sregion);
isc_region_consume(&sregion, 2);
addrlen = uint8_fromregion(&sregion);
......@@ -139,29 +143,34 @@ fromwire_opt(ARGS_FROMWIRE) {
* lengths don't make sense because the
* family is unknown.
*/
if (addrlen != 0U || scope != 0U)
if (addrlen != 0U || scope != 0U) {
return (DNS_R_OPTERR);
}
break;
case 1:
if (addrlen > 32U || scope > 32U)
if (addrlen > 32U || scope > 32U) {
return (DNS_R_OPTERR);
}
break;
case 2:
if (addrlen > 128U || scope > 128U)
if (addrlen > 128U || scope > 128U) {
return (DNS_R_OPTERR);
}
break;
default:
return (DNS_R_OPTERR);
}
addrbytes = (addrlen + 7) / 8;
if (addrbytes + 4 != length)
if (addrbytes + 4 != length) {
return (DNS_R_OPTERR);
}
if (addrbytes != 0U && (addrlen % 8) != 0) {
uint8_t bits = ~0U << (8 - (addrlen % 8));
bits &= sregion.base[addrbytes - 1];
if (bits != sregion.base[addrbytes - 1])
if (bits != sregion.base[addrbytes - 1]) {
return (DNS_R_OPTERR);
}
}
isc_region_consume(&sregion, addrbytes);
break;
......@@ -170,18 +179,29 @@ fromwire_opt(ARGS_FROMWIRE) {
/*
* Request has zero length. Response is 32 bits.
*/
if (length != 0 && length != 4)
if (length != 0 && length != 4) {
return (DNS_R_OPTERR);
}
isc_region_consume(&sregion, length);
break;
case DNS_OPT_COOKIE:
if (length != 8 && (length < 16 || length > 40))
if (length != 8 && (length < 16 || length > 40)) {
return (DNS_R_OPTERR);
}
isc_region_consume(&sregion, length);
break;
case DNS_OPT_KEY_TAG:
if (length == 0 || (length % 2) != 0)
if (length == 0 || (length % 2) != 0) {
return (DNS_R_OPTERR);
}
isc_region_consume(&sregion, length);
break;
case DNS_OPT_CLIENT_TAG:
/* FALLTHROUGH */
case DNS_OPT_SERVER_TAG:
if (length != 2) {
return (DNS_R_OPTERR);
}
isc_region_consume(&sregion, length);
break;
default:
......@@ -193,8 +213,9 @@ fromwire_opt(ARGS_FROMWIRE) {
isc_buffer_activeregion(source, &sregion);
isc_buffer_availableregion(target, &tregion);
if (tregion.length < total)
if (tregion.length < total) {
return (ISC_R_NOSPACE);
}
memmove(tregion.base, sregion.base, total);
isc_buffer_forward(source, total);
isc_buffer_add(target, total);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment