[PATCH 06/10] mDNSResponder: Update to v878.240.1
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Jun 19 11:02:20 UTC 2020
The sources can be obtained via:
https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.240.1.tar.gz
Update #4010.
---
mDNSResponder/Makefile | 2 +-
mDNSResponder/mDNSCore/DNSCommon.c | 4 ++--
mDNSResponder/mDNSCore/DNSCommon.h | 7 +++++++
mDNSResponder/mDNSCore/mDNS.c | 33 ++++++++++++++++++++++--------
mDNSResponder/mDNSCore/uDNS.c | 18 ++++++++--------
mDNSResponder/mDNSCore/uDNS.h | 2 ++
mDNSResponder/mDNSShared/dns_sd.h | 2 +-
7 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/mDNSResponder/Makefile b/mDNSResponder/Makefile
index 8b97eacc..78adbd5e 100644
--- a/mDNSResponder/Makefile
+++ b/mDNSResponder/Makefile
@@ -17,7 +17,7 @@
include $(MAKEFILEPATH)/pb_makefiles/platform.make
-MVERS = "mDNSResponder-878.230.2"
+MVERS = "mDNSResponder-878.240.1"
VER =
ifneq ($(strip $(GCC_VERSION)),)
diff --git a/mDNSResponder/mDNSCore/DNSCommon.c b/mDNSResponder/mDNSCore/DNSCommon.c
index a249b967..f3150762 100644
--- a/mDNSResponder/mDNSCore/DNSCommon.c
+++ b/mDNSResponder/mDNSCore/DNSCommon.c
@@ -3467,8 +3467,8 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
rr->resrec.rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]);
rr->resrec.rrclass = (mDNSu16)(((mDNSu16)ptr[2] << 8 | ptr[3]) & kDNSClass_Mask);
rr->resrec.rroriginalttl = (mDNSu32) ((mDNSu32)ptr[4] << 24 | (mDNSu32)ptr[5] << 16 | (mDNSu32)ptr[6] << 8 | ptr[7]);
- if (rr->resrec.rroriginalttl > 0x70000000UL / mDNSPlatformOneSecond && (mDNSs32)rr->resrec.rroriginalttl != -1)
- rr->resrec.rroriginalttl = 0x70000000UL / mDNSPlatformOneSecond;
+ if (rr->resrec.rroriginalttl > mDNSMaximumTTLSeconds && (mDNSs32)rr->resrec.rroriginalttl != -1)
+ rr->resrec.rroriginalttl = mDNSMaximumTTLSeconds;
// Note: We don't have to adjust m->NextCacheCheck here -- this is just getting a record into memory for
// us to look at. If we decide to copy it into the cache, then we'll update m->NextCacheCheck accordingly.
pktrdlength = (mDNSu16)((mDNSu16)ptr[8] << 8 | ptr[9]);
diff --git a/mDNSResponder/mDNSCore/DNSCommon.h b/mDNSResponder/mDNSCore/DNSCommon.h
index b100a400..48dfe102 100644
--- a/mDNSResponder/mDNSCore/DNSCommon.h
+++ b/mDNSResponder/mDNSCore/DNSCommon.h
@@ -110,6 +110,13 @@ extern mDNSu32 mDNSRandom(mDNSu32 max); // Returns pseudo-random result from
#define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
#define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
#define mDNSIsLetter(X) (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
+
+// We believe we have adequate safeguards to protect against cache poisoning.
+// In the event that someone does find a workable cache poisoning attack, we want to limit the lifetime of the poisoned entry.
+// We set the maximum allowable TTL to one hour.
+// With the 25% correction factor to avoid the DNS Zeno's paradox bug, that gives us an actual maximum lifetime of 75 minutes.
+
+#define mDNSMaximumTTLSeconds (mDNSu32)3600
#define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c
index 10504d09..9e1ac506 100755
--- a/mDNSResponder/mDNSCore/mDNS.c
+++ b/mDNSResponder/mDNSCore/mDNS.c
@@ -7171,7 +7171,7 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
const mDNSu8 *const limit = response->data + sizeof(response->data);
const mDNSu8 *ptr = query->data;
AuthRecord *rr;
- mDNSu32 maxttl = 0x70000000;
+ mDNSu32 maxttl = mDNSMaximumTTLSeconds;
int i;
// Initialize the response fields so we can answer the questions
@@ -8075,19 +8075,25 @@ struct UDPSocket_struct
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
};
-mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp)
+mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp, DNSQuestion ** suspiciousQ)
{
DNSQuestion *q;
for (q = m->Questions; q; q=q->next)
{
if (!tcp && !q->LocalSocket) continue;
- if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port) &&
- mDNSSameOpaque16(q->TargetQID, id) &&
+ if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port) &&
q->qtype == question->qtype &&
q->qclass == question->qclass &&
q->qnamehash == question->qnamehash &&
SameDomainName(&q->qname, &question->qname))
- return(q);
+ {
+ if (mDNSSameOpaque16(q->TargetQID, id)) return(q);
+ else
+ {
+ if (!tcp && suspiciousQ) *suspiciousQ = q;
+ return(mDNSNULL);
+ }
+ }
}
return(mDNSNULL);
}
@@ -8413,7 +8419,7 @@ mDNSlocal void mDNSCoreReceiveNoDNSSECAnswers(mDNS *const m, const DNSMessage *c
DNSQuestion pktq;
DNSQuestion *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &pktq);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &pktq, !dstaddr)) &&
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &pktq, !dstaddr, mDNSNULL)) &&
qptr->ValidatingResponse)
{
DNSQuestion *next, *q;
@@ -8457,7 +8463,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
DNSQuestion q;
DNSQuestion *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr, mDNSNULL)))
{
CacheRecord *rr, *neg = mDNSNULL;
CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname);
@@ -9037,9 +9043,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// packet number, then we deduce they are old and delete them
for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
{
- DNSQuestion q, *qptr = mDNSNULL;
+ DNSQuestion q, *qptr = mDNSNULL, *suspiciousForQ = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr, &suspiciousForQ)))
{
if (!failure)
{
@@ -9102,6 +9108,15 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
returnEarly = mDNStrue;
}
}
+ else if (!InterfaceID && suspiciousForQ)
+ {
+ // If a response is suspicious for a question, then reissue the question via TCP
+ LogInfo("mDNSCoreReceiveResponse: Server %p responded suspiciously to query %##s (%s) qID %d != rID: %d",
+ suspiciousForQ->qDNSServer, q.qname.c, DNSTypeName(q.qtype),
+ mDNSVal16(suspiciousForQ->TargetQID), mDNSVal16(response->h.id));
+ uDNS_RestartQuestionAsTCP(m, suspiciousForQ, srcaddr, srcport);
+ return;
+ }
}
if (returnEarly)
{
diff --git a/mDNSResponder/mDNSCore/uDNS.c b/mDNSResponder/mDNSCore/uDNS.c
index 2d6d14e9..1f9b1543 100755
--- a/mDNSResponder/mDNSCore/uDNS.c
+++ b/mDNSResponder/mDNSCore/uDNS.c
@@ -3925,14 +3925,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW)
{
if (!srcaddr) LogMsg("uDNS_ReceiveMsg: TCP DNS response had TC bit set: ignoring");
- else
- {
- // Don't reuse TCP connections. We might have failed over to a different DNS server
- // while the first TCP connection is in progress. We need a new TCP connection to the
- // new DNS server. So, always try to establish a new connection.
- if (qptr->tcp) { DisposeTCPConn(qptr->tcp); qptr->tcp = mDNSNULL; }
- qptr->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, qptr, mDNSNULL);
- }
+ else uDNS_RestartQuestionAsTCP(m, qptr, srcaddr, srcport);
}
}
@@ -5745,6 +5738,15 @@ mDNSexport domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mD
return mDNSNULL;
}
+mDNSexport void uDNS_RestartQuestionAsTCP(mDNS *m, DNSQuestion *const q, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
+{
+ // Don't reuse TCP connections. We might have failed over to a different DNS server
+ // while the first TCP connection is in progress. We need a new TCP connection to the
+ // new DNS server. So, always try to establish a new connection.
+ if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+ q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, q, mDNSNULL);
+}
+
mDNSlocal void FlushAddressCacheRecords(mDNS *const m)
{
mDNSu32 slot;
diff --git a/mDNSResponder/mDNSCore/uDNS.h b/mDNSResponder/mDNSCore/uDNS.h
index 27b7acee..d3141dd5 100755
--- a/mDNSResponder/mDNSCore/uDNS.h
+++ b/mDNSResponder/mDNSCore/uDNS.h
@@ -129,6 +129,8 @@ extern void uDNS_SetupWABQueries(mDNS *const m);
extern void uDNS_StartWABQueries(mDNS *const m, int queryType);
extern void uDNS_StopWABQueries(mDNS *const m, int queryType);
extern domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
+
+extern void uDNS_RestartQuestionAsTCP(mDNS *m, DNSQuestion *const q, const mDNSAddr *const srcaddr, const mDNSIPPort srcport);
typedef enum
{
diff --git a/mDNSResponder/mDNSShared/dns_sd.h b/mDNSResponder/mDNSShared/dns_sd.h
index 2f530917..3495c6e6 100644
--- a/mDNSResponder/mDNSShared/dns_sd.h
+++ b/mDNSResponder/mDNSShared/dns_sd.h
@@ -66,7 +66,7 @@
*/
#ifndef _DNS_SD_H
-#define _DNS_SD_H 8803002
+#define _DNS_SD_H 8804001
#ifdef __cplusplus
extern "C" {
--
2.26.2
More information about the devel
mailing list