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:
parent
db5e20f237
commit
c4c207a85e
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user