Skip to content

Commit c4c207a

Browse files
me-no-devigrr
authored andcommitted
Optimize MDNS to prevent overflow and endless loop (#2333)
* Optimize MDNS to prevent overflow and endless loop * Handle better non-esp services * leave debug off * better name resolution for external devices * strip name length (did not show in IDE)
1 parent db5e20f commit c4c207a

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

libraries/ESP8266mDNS/ESP8266mDNS.cpp

+48-14
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,11 @@ void MDNSResponder::_parsePacket(){
493493
return;
494494
}
495495

496-
int numAnswers = packetHeader[3];
496+
int numAnswers = packetHeader[3] + packetHeader[5];
497497
// Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet.
498498
if (numAnswers < 4) {
499499
#ifdef MDNS_DEBUG_RX
500-
Serial.println("Expected a packet with 4 answers, returning");
500+
Serial.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers);
501501
#endif
502502
_conn->flush();
503503
return;
@@ -510,11 +510,14 @@ void MDNSResponder::_parsePacket(){
510510
bool serviceMatch = false;
511511
MDNSAnswer *answer;
512512
uint8_t partsCollected = 0;
513+
uint8_t stringsRead = 0;
514+
515+
answerHostName[0] = '\0';
513516

514517
// Clear answer list
515518
if (_newQuery) {
516-
int numAnswers = _getNumAnswers();
517-
for (int n = numAnswers - 1; n >= 0; n--) {
519+
int oldAnswers = _getNumAnswers();
520+
for (int n = oldAnswers - 1; n >= 0; n--) {
518521
answer = _getAnswerFromIdx(n);
519522
os_free(answer->hostname);
520523
os_free(answer);
@@ -526,21 +529,29 @@ void MDNSResponder::_parsePacket(){
526529

527530
while (numAnswers--) {
528531
// Read name
532+
stringsRead = 0;
529533
do {
530534
tmp8 = _conn_read8();
531535
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
532536
tmp8 = _conn_read8();
533537
break;
534538
}
535-
if (tmp8 == 0x00) { // Énd of name
539+
if (tmp8 == 0x00) { // End of name
536540
break;
537541
}
542+
if(stringsRead > 3){
543+
#ifdef MDNS_DEBUG_RX
544+
Serial.println("failed to read the response name");
545+
#endif
546+
_conn->flush();
547+
return;
548+
}
538549
_conn_readS(serviceName, tmp8);
539550
serviceName[tmp8] = '\0';
540551
#ifdef MDNS_DEBUG_RX
541552
Serial.printf(" %d ", tmp8);
542553
for (int n = 0; n < tmp8; n++) {
543-
Serial.printf("%02x ", serviceName[n]);
554+
Serial.printf("%c", serviceName[n]);
544555
}
545556
Serial.println();
546557
#endif
@@ -552,23 +563,41 @@ void MDNSResponder::_parsePacket(){
552563
#endif
553564
}
554565
}
566+
stringsRead++;
555567
} while (true);
556568

557569
uint16_t answerType = _conn_read16(); // Read type
558570
uint16_t answerClass = _conn_read16(); // Read class
559571
uint32_t answerTtl = _conn_read32(); // Read ttl
560572
uint16_t answerRdlength = _conn_read16(); // Read rdlength
561573

574+
if(answerRdlength > 255){
575+
if(answerType == MDNS_TYPE_TXT && answerRdlength < 1460){
576+
while(--answerRdlength) _conn->read();
577+
} else {
578+
#ifdef MDNS_DEBUG_RX
579+
Serial.printf("Data len too long! %u\n", answerRdlength);
580+
#endif
581+
_conn->flush();
582+
return;
583+
}
584+
}
585+
562586
#ifdef MDNS_DEBUG_RX
563587
Serial.printf("type: %04x rdlength: %d\n", answerType, answerRdlength);
564588
#endif
565589

566590
if (answerType == MDNS_TYPE_PTR) {
567591
partsCollected |= 0x01;
568592
_conn_readS(hostName, answerRdlength); // Read rdata
593+
if(hostName[answerRdlength-2] & 0xc0){
594+
memcpy(answerHostName, hostName+1, answerRdlength-3);
595+
answerHostName[answerRdlength-3] = '\0';
596+
}
569597
#ifdef MDNS_DEBUG_RX
598+
Serial.printf("PTR %d ", answerRdlength);
570599
for (int n = 0; n < answerRdlength; n++) {
571-
Serial.printf("%02x ", hostName[n]);
600+
Serial.printf("%c", hostName[n]);
572601
}
573602
Serial.println();
574603
#endif
@@ -578,8 +607,9 @@ void MDNSResponder::_parsePacket(){
578607
partsCollected |= 0x02;
579608
_conn_readS(hostName, answerRdlength); // Read rdata
580609
#ifdef MDNS_DEBUG_RX
610+
Serial.printf("TXT %d ", answerRdlength);
581611
for (int n = 0; n < answerRdlength; n++) {
582-
Serial.printf("%02x ", hostName[n]);
612+
Serial.printf("%c", hostName[n]);
583613
}
584614
Serial.println();
585615
#endif
@@ -594,14 +624,16 @@ void MDNSResponder::_parsePacket(){
594624
// Read hostname
595625
tmp8 = _conn_read8();
596626
if (tmp8 & 0xC0) { // Compressed pointer (not supported)
627+
#ifdef MDNS_DEBUG_RX
597628
Serial.println("Skipping compressed pointer");
629+
#endif
598630
tmp8 = _conn_read8();
599631
}
600632
else {
601633
_conn_readS(answerHostName, tmp8);
602634
answerHostName[tmp8] = '\0';
603635
#ifdef MDNS_DEBUG_RX
604-
Serial.printf(" %d ", tmp8);
636+
Serial.printf("SRV %d ", tmp8);
605637
for (int n = 0; n < tmp8; n++) {
606638
Serial.printf("%02x ", answerHostName[n]);
607639
}
@@ -621,7 +653,7 @@ void MDNSResponder::_parsePacket(){
621653
}
622654
else {
623655
#ifdef MDNS_DEBUG_RX
624-
Serial.printf("Ignoring unsupported type %d\n", tmp8);
656+
Serial.printf("Ignoring unsupported type %02x\n", tmp8);
625657
#endif
626658
for (int n = 0; n < answerRdlength; n++)
627659
(void)_conn_read8();
@@ -654,6 +686,8 @@ void MDNSResponder::_parsePacket(){
654686
}
655687
answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1);
656688
os_strcpy(answer->hostname, answerHostName);
689+
_conn->flush();
690+
return;
657691
}
658692
}
659693

@@ -663,7 +697,7 @@ void MDNSResponder::_parsePacket(){
663697

664698
// PARSE REQUEST NAME
665699

666-
hostNameLen = _conn_read8();
700+
hostNameLen = _conn_read8() % 255;
667701
_conn_readS(hostName, hostNameLen);
668702
hostName[hostNameLen] = '\0';
669703

@@ -685,7 +719,7 @@ void MDNSResponder::_parsePacket(){
685719
}
686720

687721
if(!serviceParsed){
688-
serviceNameLen = _conn_read8();
722+
serviceNameLen = _conn_read8() % 255;
689723
_conn_readS(serviceName, serviceNameLen);
690724
serviceName[serviceNameLen] = '\0';
691725

@@ -718,7 +752,7 @@ void MDNSResponder::_parsePacket(){
718752
}
719753

720754
if(!protoParsed){
721-
protoNameLen = _conn_read8();
755+
protoNameLen = _conn_read8() % 255;
722756
_conn_readS(protoName, protoNameLen);
723757
protoName[protoNameLen] = '\0';
724758
if(protoNameLen == 4 && protoName[0] == '_'){
@@ -740,7 +774,7 @@ void MDNSResponder::_parsePacket(){
740774

741775
if(!localParsed){
742776
char localName[32];
743-
uint8_t localNameLen = _conn_read8();
777+
uint8_t localNameLen = _conn_read8() % 31;
744778
_conn_readS(localName, localNameLen);
745779
localName[localNameLen] = '\0';
746780
tmp = _conn_read8();

0 commit comments

Comments
 (0)