diff --git a/src/dns.c b/src/dns.c index 3aa39ffa..845368f8 100644 --- a/src/dns.c +++ b/src/dns.c @@ -2142,6 +2142,10 @@ hsk_dns_name_parse( // Only occurs at end of name (zero-length label aka ".") if (c == 0x00) { + // Almost made it! Last byte exceeds max. + if (noff + 1 > HSK_DNS_MAX_NAME) + return -1; + if (name) name[noff] = 0x00; @@ -2249,6 +2253,12 @@ hsk_dns_name_serialize( // End of name "." if (label == 0x00) { + // Almost made it! Last byte exceeds max + if (1 + noff > HSK_DNS_MAX_NAME) { + *len = off; + return false; + } + if (data) data[off] = 0x00; diff --git a/test/data/record_read_vectors.h b/test/data/record_read_vectors.h index c818a515..2fef2954 100644 --- a/test/data/record_read_vectors.h +++ b/test/data/record_read_vectors.h @@ -14,10 +14,17 @@ typedef struct record_read_vector { uint16_t type; char name1[HSK_DNS_MAX_NAME_STRING]; char name2[HSK_DNS_MAX_NAME_STRING]; - uint8_t data[HSK_DNS_MAX_NAME]; + uint8_t data[HSK_DNS_MAX_NAME + 1]; // extended to fit invalid data size_t data_len; + bool valid; + uint8_t invalidname[HSK_DNS_MAX_NAME + 1]; // extended to fit invalid data + size_t invalidname_len; } record_read_vector_t; +typedef struct { + uint8_t target[HSK_DNS_MAX_NAME_STRING]; // extended to fit invalid data +} hsk_dns_invalid_cname_rd_t; + /* * Vectors */ @@ -38,14 +45,19 @@ static char *record_read_msg_qname = "xxxx.rec.test."; // Currently we only test for reading/writing names, // other data in records is ignored (commented out for future tests). -static const record_read_vector_t record_read_vectors_valid[] = { +static const record_read_vector_t record_read_vectors[] = { + /* + * VALID + */ + // local nameserver { HSK_DNS_NS, "ns.rec.test.", "", "\x02ns\xc0\x11", - 5 + 5, + true }, // non-local nameserver @@ -54,7 +66,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "ns.example.com.", "", "\x02ns\x07""example\x03""com\x00", - 16 + 16, + true }, // local alias @@ -63,7 +76,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "name.rec.test.", "", "\x04name\xc0\x11", - 7 + 7, + true }, // non-local alias @@ -72,7 +86,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "name.example.com.", "", "\x04name\x07""example\x03""com\x00", - 18 + 18, + true }, // max label length (63) @@ -81,7 +96,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "123456789012345678901234567890123456789012345678901234567890123.example.com.", "", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x07""example\x03""com\x00", - 77 + 77, + true }, // local max name length (255) @@ -90,7 +106,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012.rec.test.", "", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x34""1234567890123456789012345678901234567890123456789012\xc0\x11", - 247 + 247, + true }, // non-local max name length (255) @@ -99,7 +116,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.", "", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3d""1234567890123456789012345678901234567890123456789012345678901\x00", - 255 + 255, + true }, // local names @@ -109,7 +127,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "hostmaster.test.rec.", /*2013051201 3600 3600 604800 120*/ "\x02ns\xc0\x11\x0ahostmaster\x04test\x03rec\x00\x77\xfc\xb9\x41\x00\x00\x0e\x10\x00\x00\x0e\x10\x00\x09\x3a\x80\x00\x00\x00\x78", - 46 + 46, + true }, // non-local names @@ -119,7 +138,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "hostmaster.example.com.", /*2013051201 3600 3600 604800 120*/ "\x02ns\x07""example\x03""com\x00\x0ahostmaster\xc0\x28\x77\xfc\xb9\x41\x00\x00\x0e\x10\x00\x00\x0e\x10\x00\x09\x3a\x80\x00\x00\x00\x78", - 49 + 49, + true }, // local name @@ -128,7 +148,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "ptr.rec.test.", "", "\x03ptr\xc0\x11", - 6 + 6, + true }, // non-local name @@ -137,7 +158,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "ptr.example.com.", "", "\x03ptr\x07""example\x03""com\x00", - 17 + 17, + true }, @@ -148,7 +170,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "mx.rec.test.", "", "\x00\x0a\x02mx\xc0\x11", - 7 + 7, + true }, // non-local name @@ -158,7 +181,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "mx.example.com.", "", "\x00\x14\x02mx\x07""example\x03""com\x00", - 18 + 18, + true }, // root label @@ -168,7 +192,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { ".", "", "\x00\x14\x00", - 3 + 3, + true }, // local name @@ -177,7 +202,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "admin.rec.test.", "admin-info.rec.test.", "\x05""admin\x03rec\x04test\x00\x0a""admin-info\x03rec\x04test\x00", - 37 + 37, + true }, // non-local name @@ -186,7 +212,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "admin.example.com.", "admin-info.example.com.", "\x05""admin\x07""example\x03""com\x00\x0a""admin-info\x07""example\x03""com\x00", - 43 + 43, + true }, // local name @@ -196,7 +223,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "sip.rec.test.", "", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x03rec\x04test\x00", - 20 + 20, + true }, // non-local name @@ -206,7 +234,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "sip.example.com.", "", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x07""example\x03""com\x00", - 24 + 24, + true }, // root name @@ -216,7 +245,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { ".", "", "\x00\x0a\x00\x0a\x13\xc4\x00", - 7 + 7, + true }, { @@ -226,7 +256,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { "", /*ecWKD/OsdAiXpbM/sgPT82KVD/WiQnnqcxoJgiH3ixHa+LOAcYU7FG7V4BRRJxLriY1e0rB2gAs3kCel9D4bzfK6wAqG4Di/eHUgHptRlaR2ycELJ4t1pjzrnuGiIzA1wM2izRmeE+Xoy1367Qu0pOz5DLzTfQITWFsB2iUzN4Y=*/ "\x00\x06\x08\x03\x00\x00\x01\x2c\x51\x9d\x5c\x00\x51\x8a\xe7\x00\xd3\xc8\x03\x72\x65\x63\x04\x74\x65\x73\x74\x00\x79\xc5\x8a\x0f\xf3\xac\x74\x08\x97\xa5\xb3\x3f\xb2\x03\xd3\xf3\x62\x95\x0f\xf5\xa2\x42\x79\xea\x73\x1a\x09\x82\x21\xf7\x8b\x11\xda\xf8\xb3\x80\x71\x85\x3b\x14\x6e\xd5\xe0\x14\x51\x27\x12\xeb\x89\x8d\x5e\xd2\xb0\x76\x80\x0b\x37\x90\x27\xa5\xf4\x3e\x1b\xcd\xf2\xba\xc0\x0a\x86\xe0\x38\xbf\x78\x75\x20\x1e\x9b\x51\x95\xa4\x76\xc9\xc1\x0b\x27\x8b\x75\xa6\x3c\xeb\x9e\xe1\xa2\x23\x30\x35\xc0\xcd\xa2\xcd\x19\x9e\x13\xe5\xe8\xcb\x5d\xfa\xed\x0b\xb4\xa4\xec\xf9\x0c\xbc\xd3\x7d\x02\x13\x58\x5b\x01\xda\x25\x33\x37\x86", - 156 + 156, + true }, { @@ -235,7 +266,8 @@ static const record_read_vector_t record_read_vectors_valid[] = { /*A NS SOA MX AAAA RRSIG NSEC DNSKEY*/ "", "\x01""a\x03rec\x04test\x00\x00\x07\x62\x01\x00\x08\x00\x03\x80", - 21 + 21, + true }, // TODO: Fix the 255-byte limit on URI record tarets @@ -253,15 +285,43 @@ static const record_read_vector_t record_read_vectors_valid[] = { // "", // "\x00\x0a\x00\x01\x66\x74\x70\x3a\x2f\x2f\x66\x74\x70\x31\x2e\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x70\x75\x62\x6c\x69\x63\x2f\x77\x69\x74\x68\x2f\x61\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x6c\x6f\x6e\x67\x2f\x75\x72\x6c" // } -}; -// static const record_read_vector_t record_read_vectors_invalid[] = { -// // empty label, must be broken. No serilization exists for reverse test so use dummy -// {HSK_DNS_CNAME, "name..example.com.", "", "\xff.dummy"}, -// // overly large label (64), must be broken -// {HSK_DNS_CNAME, "1234567890123456789012345678901234567890123456789012345678901234.example.com.", "", "\x40""1234567890123456789012345678901234567890123456789012345678901234\x07""example\x03""com\x00"}, -// // local overly large name (256), must be broken -// {HSK_DNS_CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123.rec.test.", "", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x35""12345678901234567890123456789012345678901234567890123\xc0\x11"}, -// // non-local overly large name (256), must be broken -// {HSK_DNS_CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012.", "", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3e""12345678901234567890123456789012345678901234567890123456789012\x00"} -// }; + /* + * INVALID + */ + + // overly large label (64), must be broken + { + HSK_DNS_CNAME, + "1234567890123456789012345678901234567890123456789012345678901234.example.com.", + "", + "\x40""1234567890123456789012345678901234567890123456789012345678901234\x07""example\x03""com\x00", + 78, + false, + "\x40""1234567890123456789012345678901234567890123456789012345678901234\x07""example\x03""com\x00", + 78 + }, + + // local overly large name (256), must be broken + { + HSK_DNS_CNAME, + "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123.rec.test.", + "", + "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x35""12345678901234567890123456789012345678901234567890123\xc0\x11", + 238, + false, + "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x35""12345678901234567890123456789012345678901234567890123\x03rec\x04test\x00", + 256 + }, + // non-local overly large name (256), must be broken + { + HSK_DNS_CNAME, + "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012.", + "", + "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3e""12345678901234567890123456789012345678901234567890123456789012\x00", + 256, + false, + "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3e""12345678901234567890123456789012345678901234567890123456789012\x00", + 256 + } +}; diff --git a/test/hnsd-test.c b/test/hnsd-test.c index 0c602d20..6f267704 100644 --- a/test/hnsd-test.c +++ b/test/hnsd-test.c @@ -115,8 +115,8 @@ void test_hsk_dns_msg_read() { printf(" test_dns_msg_read\n"); - for (int i = 0; i < ARRAY_SIZE(record_read_vectors_valid); i++) { - record_read_vector_t record_read_vector = record_read_vectors_valid[i]; + for (int i = 0; i < ARRAY_SIZE(record_read_vectors); i++) { + record_read_vector_t record_read_vector = record_read_vectors[i]; printf(" TYPE:%02d %s\n",record_read_vector.type, record_read_vector.name1); // Build DNS message from test vector @@ -136,7 +136,11 @@ test_hsk_dns_msg_read() { // Read hsk_dns_msg_t *msg = hsk_dns_msg_alloc(); data_ = (uint8_t *)&data; - hsk_dns_msg_read(&data_, &total_len, msg); + bool success = hsk_dns_msg_read(&data_, &total_len, msg); + assert(success == record_read_vector.valid); + + if (!success) + goto done; // Grab first answer hsk_dns_rr_t *rr = msg->an.items[0]; @@ -214,15 +218,16 @@ test_hsk_dns_msg_read() { } } +done: hsk_dns_msg_free(msg); } } void -test_hsk_dns_msg_write(){ +test_hsk_dns_msg_write() { printf(" test_hsk_dns_msg_write\n"); - for (int i = 0; i < ARRAY_SIZE(record_read_vectors_valid); i++) { - record_read_vector_t record_read_vector = record_read_vectors_valid[i]; + for (int i = 0; i < ARRAY_SIZE(record_read_vectors); i++) { + record_read_vector_t record_read_vector = record_read_vectors[i]; // Build expected DNS message from test vector size_t meta_len = 2 + 2 + 4 + 2; // type, class, ttl, rd size @@ -245,7 +250,13 @@ test_hsk_dns_msg_write(){ rr->type = record_read_vector.type; rr->class = HSK_DNS_IN; rr->ttl = 0; - rr->rd = hsk_dns_rd_alloc(record_read_vector.type); + + if (record_read_vector.valid) { + rr->rd = hsk_dns_rd_alloc(record_read_vector.type); + } else { + rr->rd = malloc(sizeof(hsk_dns_invalid_cname_rd_t)); + } + hsk_dns_rrs_push(&msg->an, rr); // Write names, convert from presentation format @@ -265,7 +276,11 @@ test_hsk_dns_msg_write(){ } case HSK_DNS_CNAME: { hsk_dns_cname_rd_t *cname = rr->rd; - hsk_dns_name_from_string(record_read_vector.name1, cname->target); + if (record_read_vector.valid) { + hsk_dns_name_from_string(record_read_vector.name1, cname->target); + } else { + memcpy(cname->target, record_read_vector.invalidname, record_read_vector.invalidname_len); + } break; } case HSK_DNS_PTR: { @@ -285,9 +300,15 @@ test_hsk_dns_msg_write(){ uint8_t actual[total_len]; uint8_t *actual_ = (uint8_t *)&actual; - hsk_dns_msg_write(msg, &actual_); - - assert(memcmp(&data, &actual, total_len) == 0); + int written = hsk_dns_msg_write(msg, &actual_); + + if (record_read_vector.valid) { + assert(written == total_len); + assert(memcmp(&data, &actual, total_len) == 0); + } else { + assert(written != total_len); + assert(memcmp(&data, &actual, total_len) != 0); + } // Also frees rr and rd hsk_dns_msg_free(msg);