diff --git a/CHANGES b/CHANGES index 83fb0224d9..7280717268 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3663. [bug] Address bugs in dns_rdata_fromstruct and + dns_rdata_tostruct for WKS and ISDN types. [RT #34910] + 3662. [bug] 'host' could die if a UDP query timed out. [RT #34870] --- 9.10.0a1 released --- diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c index 5aac73f371..feb9555031 100644 --- a/lib/dns/rdata/generic/isdn_20.c +++ b/lib/dns/rdata/generic/isdn_20.c @@ -127,6 +127,8 @@ fromstruct_isdn(ARGS_FROMSTRUCT) { RETERR(uint8_tobuffer(isdn->isdn_len, target)); RETERR(mem_tobuffer(target, isdn->isdn, isdn->isdn_len)); + if (isdn->subaddress == NULL && isdn->subaddress_len == 0) + return (ISC_R_SUCCESS); RETERR(uint8_tobuffer(isdn->subaddress_len, target)); return (mem_tobuffer(target, isdn->subaddress, isdn->subaddress_len)); } @@ -153,11 +155,17 @@ tostruct_isdn(ARGS_TOSTRUCT) { return (ISC_R_NOMEMORY); isc_region_consume(&r, isdn->isdn_len); - isdn->subaddress_len = uint8_fromregion(&r); - isc_region_consume(&r, 1); - isdn->subaddress = mem_maybedup(mctx, r.base, isdn->subaddress_len); - if (isdn->subaddress == NULL) - goto cleanup; + if (r.length == 0) { + isdn->subaddress_len = 0; + isdn->subaddress = NULL; + } else { + isdn->subaddress_len = uint8_fromregion(&r); + isc_region_consume(&r, 1); + isdn->subaddress = mem_maybedup(mctx, r.base, + isdn->subaddress_len); + if (isdn->subaddress == NULL) + goto cleanup; + } isdn->mctx = mctx; return (ISC_R_SUCCESS); diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c index 1da2611da9..124205d2ca 100644 --- a/lib/dns/rdata/in_1/wks_11.c +++ b/lib/dns/rdata/in_1/wks_11.c @@ -278,7 +278,7 @@ fromstruct_in_wks(ARGS_FROMSTRUCT) { a = ntohl(wks->in_addr.s_addr); RETERR(uint32_tobuffer(a, target)); - RETERR(uint16_tobuffer(wks->protocol, target)); + RETERR(uint8_tobuffer(wks->protocol, target)); return (mem_tobuffer(target, wks->map, wks->map_len)); } @@ -300,8 +300,8 @@ tostruct_in_wks(ARGS_TOSTRUCT) { n = uint32_fromregion(®ion); wks->in_addr.s_addr = htonl(n); isc_region_consume(®ion, 4); - wks->protocol = uint16_fromregion(®ion); - isc_region_consume(®ion, 2); + wks->protocol = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); wks->map_len = region.length; wks->map = mem_maybedup(mctx, region.base, region.length); if (wks->map == NULL) diff --git a/lib/dns/tests/rdata_test.c b/lib/dns/tests/rdata_test.c index 37f9792f06..747ef4bb8c 100644 --- a/lib/dns/tests/rdata_test.c +++ b/lib/dns/tests/rdata_test.c @@ -227,12 +227,162 @@ ATF_TC_BODY(edns_client_subnet, tc) { } } +ATF_TC(wks); +ATF_TC_HEAD(wks, tc) { + atf_tc_set_md_var(tc, "descr", "wks to/from struct"); +} +ATF_TC_BODY(wks, tc) { + struct { + unsigned char data[64]; + size_t len; + isc_boolean_t ok; + } test_data[] = { + { + /* too short */ + { 0x00, 0x08, 0x0, 0x00 }, 4, ISC_FALSE + }, + { + /* minimal TCP */ + { 0x00, 0x08, 0x0, 0x00, 6 }, 5, ISC_TRUE + }, + { + /* minimal UDP */ + { 0x00, 0x08, 0x0, 0x00, 17 }, 5, ISC_TRUE + }, + { + /* minimal other */ + { 0x00, 0x08, 0x0, 0x00, 1 }, 5, ISC_TRUE + }, + { + /* sentinal */ + { 0x00 }, 0, ISC_FALSE + } + }; + unsigned char buf1[1024*1024]; + unsigned char buf2[1024*1024]; + isc_buffer_t source, target1, target2; + dns_rdata_t rdata; + dns_decompress_t dctx; + isc_result_t result; + size_t i; + dns_rdata_in_wks_t wks; + + UNUSED(tc); + + for (i = 0; test_data[i].len != 0; i++) { + isc_buffer_init(&source, test_data[i].data, test_data[i].len); + isc_buffer_add(&source, test_data[i].len); + isc_buffer_setactive(&source, test_data[i].len); + isc_buffer_init(&target1, buf1, sizeof(buf1)); + dns_rdata_init(&rdata); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); + result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, + dns_rdatatype_wks, &source, + &dctx, 0, &target1); + dns_decompress_invalidate(&dctx); + if (test_data[i].ok) + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + else + ATF_REQUIRE(result != ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + continue; + result = dns_rdata_tostruct(&rdata, &wks, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&target2, buf2, sizeof(buf2)); + dns_rdata_reset(&rdata); + result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, + dns_rdatatype_wks, &wks, + &target2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), + test_data[i].len); + ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, + test_data[i].len), 0); + } +} + +ATF_TC(isdn); +ATF_TC_HEAD(isdn, tc) { + atf_tc_set_md_var(tc, "descr", "isdn to/from struct"); +} +ATF_TC_BODY(isdn, tc) { + struct { + unsigned char data[64]; + size_t len; + isc_boolean_t ok; + } test_data[] = { + { + /* "" */ + { 0x00 }, 1, ISC_TRUE + }, + { + /* "\001" */ + { 0x1, 0x01 }, 2, ISC_TRUE + }, + { + /* "\001" "" */ + { 0x1, 0x01, 0x00 }, 3, ISC_TRUE + }, + { + /* "\000" "\001" */ + { 0x1, 0x01, 0x01, 0x01 }, 4, ISC_TRUE + }, + { + /* sentinal */ + { 0x00 }, 0, ISC_FALSE + } + }; + unsigned char buf1[1024*1024]; + unsigned char buf2[1024*1024]; + isc_buffer_t source, target1, target2; + dns_rdata_t rdata; + dns_decompress_t dctx; + isc_result_t result; + size_t i; + dns_rdata_isdn_t isdn; + + UNUSED(tc); + + for (i = 0; test_data[i].len != 0; i++) { + isc_buffer_init(&source, test_data[i].data, test_data[i].len); + isc_buffer_add(&source, test_data[i].len); + isc_buffer_setactive(&source, test_data[i].len); + isc_buffer_init(&target1, buf1, sizeof(buf1)); + dns_rdata_init(&rdata); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); + result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, + dns_rdatatype_isdn, &source, + &dctx, 0, &target1); + dns_decompress_invalidate(&dctx); + if (test_data[i].ok) + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + else + ATF_REQUIRE(result != ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + continue; + result = dns_rdata_tostruct(&rdata, &isdn, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + isc_buffer_init(&target2, buf2, sizeof(buf2)); + dns_rdata_reset(&rdata); + result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, + dns_rdatatype_isdn, &isdn, + &target2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), + test_data[i].len); + ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, + test_data[i].len), 0); + } +} + /* * Main */ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, hip); ATF_TP_ADD_TC(tp, edns_client_subnet); + ATF_TP_ADD_TC(tp, wks); + ATF_TP_ADD_TC(tp, isdn); return (atf_no_error()); }