1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

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)
This commit is contained in:
Me No Dev 2016-08-01 06:48:23 +03:00 committed by Ivan Grokhotkov
parent db5e20f237
commit c4c207a85e

View File

@ -493,11 +493,11 @@ void MDNSResponder::_parsePacket(){
return; return;
} }
int numAnswers = packetHeader[3]; int numAnswers = packetHeader[3] + packetHeader[5];
// 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. // 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.
if (numAnswers < 4) { if (numAnswers < 4) {
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.println("Expected a packet with 4 answers, returning"); Serial.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers);
#endif #endif
_conn->flush(); _conn->flush();
return; return;
@ -510,11 +510,14 @@ void MDNSResponder::_parsePacket(){
bool serviceMatch = false; bool serviceMatch = false;
MDNSAnswer *answer; MDNSAnswer *answer;
uint8_t partsCollected = 0; uint8_t partsCollected = 0;
uint8_t stringsRead = 0;
answerHostName[0] = '\0';
// Clear answer list // Clear answer list
if (_newQuery) { if (_newQuery) {
int numAnswers = _getNumAnswers(); int oldAnswers = _getNumAnswers();
for (int n = numAnswers - 1; n >= 0; n--) { for (int n = oldAnswers - 1; n >= 0; n--) {
answer = _getAnswerFromIdx(n); answer = _getAnswerFromIdx(n);
os_free(answer->hostname); os_free(answer->hostname);
os_free(answer); os_free(answer);
@ -526,21 +529,29 @@ void MDNSResponder::_parsePacket(){
while (numAnswers--) { while (numAnswers--) {
// Read name // Read name
stringsRead = 0;
do { do {
tmp8 = _conn_read8(); tmp8 = _conn_read8();
if (tmp8 & 0xC0) { // Compressed pointer (not supported) if (tmp8 & 0xC0) { // Compressed pointer (not supported)
tmp8 = _conn_read8(); tmp8 = _conn_read8();
break; break;
} }
if (tmp8 == 0x00) { // Énd of name if (tmp8 == 0x00) { // End of name
break; break;
} }
if(stringsRead > 3){
#ifdef MDNS_DEBUG_RX
Serial.println("failed to read the response name");
#endif
_conn->flush();
return;
}
_conn_readS(serviceName, tmp8); _conn_readS(serviceName, tmp8);
serviceName[tmp8] = '\0'; serviceName[tmp8] = '\0';
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf(" %d ", tmp8); Serial.printf(" %d ", tmp8);
for (int n = 0; n < tmp8; n++) { for (int n = 0; n < tmp8; n++) {
Serial.printf("%02x ", serviceName[n]); Serial.printf("%c", serviceName[n]);
} }
Serial.println(); Serial.println();
#endif #endif
@ -552,6 +563,7 @@ void MDNSResponder::_parsePacket(){
#endif #endif
} }
} }
stringsRead++;
} while (true); } while (true);
uint16_t answerType = _conn_read16(); // Read type uint16_t answerType = _conn_read16(); // Read type
@ -559,6 +571,18 @@ void MDNSResponder::_parsePacket(){
uint32_t answerTtl = _conn_read32(); // Read ttl uint32_t answerTtl = _conn_read32(); // Read ttl
uint16_t answerRdlength = _conn_read16(); // Read rdlength uint16_t answerRdlength = _conn_read16(); // Read rdlength
if(answerRdlength > 255){
if(answerType == MDNS_TYPE_TXT && answerRdlength < 1460){
while(--answerRdlength) _conn->read();
} else {
#ifdef MDNS_DEBUG_RX
Serial.printf("Data len too long! %u\n", answerRdlength);
#endif
_conn->flush();
return;
}
}
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf("type: %04x rdlength: %d\n", answerType, answerRdlength); Serial.printf("type: %04x rdlength: %d\n", answerType, answerRdlength);
#endif #endif
@ -566,9 +590,14 @@ void MDNSResponder::_parsePacket(){
if (answerType == MDNS_TYPE_PTR) { if (answerType == MDNS_TYPE_PTR) {
partsCollected |= 0x01; partsCollected |= 0x01;
_conn_readS(hostName, answerRdlength); // Read rdata _conn_readS(hostName, answerRdlength); // Read rdata
if(hostName[answerRdlength-2] & 0xc0){
memcpy(answerHostName, hostName+1, answerRdlength-3);
answerHostName[answerRdlength-3] = '\0';
}
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf("PTR %d ", answerRdlength);
for (int n = 0; n < answerRdlength; n++) { for (int n = 0; n < answerRdlength; n++) {
Serial.printf("%02x ", hostName[n]); Serial.printf("%c", hostName[n]);
} }
Serial.println(); Serial.println();
#endif #endif
@ -578,8 +607,9 @@ void MDNSResponder::_parsePacket(){
partsCollected |= 0x02; partsCollected |= 0x02;
_conn_readS(hostName, answerRdlength); // Read rdata _conn_readS(hostName, answerRdlength); // Read rdata
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf("TXT %d ", answerRdlength);
for (int n = 0; n < answerRdlength; n++) { for (int n = 0; n < answerRdlength; n++) {
Serial.printf("%02x ", hostName[n]); Serial.printf("%c", hostName[n]);
} }
Serial.println(); Serial.println();
#endif #endif
@ -594,14 +624,16 @@ void MDNSResponder::_parsePacket(){
// Read hostname // Read hostname
tmp8 = _conn_read8(); tmp8 = _conn_read8();
if (tmp8 & 0xC0) { // Compressed pointer (not supported) if (tmp8 & 0xC0) { // Compressed pointer (not supported)
#ifdef MDNS_DEBUG_RX
Serial.println("Skipping compressed pointer"); Serial.println("Skipping compressed pointer");
#endif
tmp8 = _conn_read8(); tmp8 = _conn_read8();
} }
else { else {
_conn_readS(answerHostName, tmp8); _conn_readS(answerHostName, tmp8);
answerHostName[tmp8] = '\0'; answerHostName[tmp8] = '\0';
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf(" %d ", tmp8); Serial.printf("SRV %d ", tmp8);
for (int n = 0; n < tmp8; n++) { for (int n = 0; n < tmp8; n++) {
Serial.printf("%02x ", answerHostName[n]); Serial.printf("%02x ", answerHostName[n]);
} }
@ -621,7 +653,7 @@ void MDNSResponder::_parsePacket(){
} }
else { else {
#ifdef MDNS_DEBUG_RX #ifdef MDNS_DEBUG_RX
Serial.printf("Ignoring unsupported type %d\n", tmp8); Serial.printf("Ignoring unsupported type %02x\n", tmp8);
#endif #endif
for (int n = 0; n < answerRdlength; n++) for (int n = 0; n < answerRdlength; n++)
(void)_conn_read8(); (void)_conn_read8();
@ -654,6 +686,8 @@ void MDNSResponder::_parsePacket(){
} }
answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1); answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1);
os_strcpy(answer->hostname, answerHostName); os_strcpy(answer->hostname, answerHostName);
_conn->flush();
return;
} }
} }
@ -663,7 +697,7 @@ void MDNSResponder::_parsePacket(){
// PARSE REQUEST NAME // PARSE REQUEST NAME
hostNameLen = _conn_read8(); hostNameLen = _conn_read8() % 255;
_conn_readS(hostName, hostNameLen); _conn_readS(hostName, hostNameLen);
hostName[hostNameLen] = '\0'; hostName[hostNameLen] = '\0';
@ -685,7 +719,7 @@ void MDNSResponder::_parsePacket(){
} }
if(!serviceParsed){ if(!serviceParsed){
serviceNameLen = _conn_read8(); serviceNameLen = _conn_read8() % 255;
_conn_readS(serviceName, serviceNameLen); _conn_readS(serviceName, serviceNameLen);
serviceName[serviceNameLen] = '\0'; serviceName[serviceNameLen] = '\0';
@ -718,7 +752,7 @@ void MDNSResponder::_parsePacket(){
} }
if(!protoParsed){ if(!protoParsed){
protoNameLen = _conn_read8(); protoNameLen = _conn_read8() % 255;
_conn_readS(protoName, protoNameLen); _conn_readS(protoName, protoNameLen);
protoName[protoNameLen] = '\0'; protoName[protoNameLen] = '\0';
if(protoNameLen == 4 && protoName[0] == '_'){ if(protoNameLen == 4 && protoName[0] == '_'){
@ -740,7 +774,7 @@ void MDNSResponder::_parsePacket(){
if(!localParsed){ if(!localParsed){
char localName[32]; char localName[32];
uint8_t localNameLen = _conn_read8(); uint8_t localNameLen = _conn_read8() % 31;
_conn_readS(localName, localNameLen); _conn_readS(localName, localNameLen);
localName[localNameLen] = '\0'; localName[localNameLen] = '\0';
tmp = _conn_read8(); tmp = _conn_read8();