Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / mDNSCore / dnssec.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "mDNSEmbeddedAPI.h"
19 #include "DNSSECSupport.h"
20 #include "DNSCommon.h"
21 #include "dnssec.h"
22 #include "CryptoAlg.h"
23 #include "nsec.h"
24 #include "nsec3.h"
25
26 // Define DNSSEC_DISABLED to remove all the DNSSEC functionality
27 // and use the stub functions implemented later in this file.
28
29 #ifndef DNSSEC_DISABLED
30
31 //#define DNSSEC_DEBUG
32
33 #ifdef DNSSEC_DEBUG
34 #define debugdnssec LogMsg
35 #else
36 #define debugdnssec debug_noop
37 #endif
38 //
39 // Implementation Notes
40 //
41 // The entry point to DNSSEC Verification is VerifySignature. This function is called from the "core" when
42 // the answer delivered to the application needs DNSSEC validation. If a question needs DNSSEC
43 // validation, "ValidationRequired" would be set. As we need to issue more queries to validate the
44 // original question, we create another question as part of the verification process (question is part of
45 // DNSSECVerifier). This question sets "ValidatingResponse" to distinguish itself from the original
46 // question. Without this, it will be a duplicate and never sent out. The "core" almost treats both the
47 // types identically (like adding EDNS0 option with DO bit etc.) except for a few differences. When RRSIGs
48 // are added to the cache, "ValidatingResponse" question gets called back as long as the typeCovered matches
49 // the question's qtype. See the comment in DNSSECRecordAnswersQuestion for the details. The other big
50 // difference is that "ValidationRequired" question kicks off the verification process by calling into
51 // "VerifySignature" whereas ValidationResponse don't do that as it gets callback for its questions.
52 //
53 // VerifySignature does not retain the original question that started the verification process. It just
54 // remembers the name and the type. It takes a snapshot of the cache at that instance which will be
55 // verified using DNSSEC. If the cache changes subsequently e.g., network change etc., it will be detected
56 // when the validation is completed. If there is a change, it will be revalidated.
57 //
58 // The verification flow looks like this:
59 //
60 // VerifySignature -> StartDNSSECVerification - GetAllRRSetsForVerification -> FinishDNSSECVerification -> VerifySignature
61 //
62 // Verification is a recursive process. It stops when we find a trust anchor or if we have recursed too deep.
63 //
64 // If the original question resulted in NODATA/NXDOMAIN error, there should have been NSECs as part of the response.
65 // These nsecs are cached along with the negative cache record. These are validated using ValidateWithNSECS called
66 // from Verifysignature.
67 //
68 // The flow in this case looks like this:
69 //
70 // VerifySignature -> ValidateWithNSECS -> {NoDataProof, NameErrorProof} -> VerifyNSECS -> StartDNSSECVerification
71 //
72 // Once the DNSSEC verification is started, it is similar to the previous flow described above. When the verification
73 // is done, DNSSECPositiveValidationCB or DNSSECNegativeValidationCB will be called which will then deliver the
74 // validation results to the original question that started the validation.
75 //
76 // Insecure proofs are done when the verification ends up bogus. The flow would look like this
77 //
78 // VerifySignature -> StartDNSSECVerification - GetAllRRSetsForVerification -> FinishDNSSECVerification -> DNSSECValidationCB
79 // {DNSSECPositiveValidationCB, DNSSECNegativeValidationCB} -> ProveInsecure -> VerifySignaure ->
80 //
81 // ProveInsecure finds the break in trust in a top-down fashion.
82 //
83 // Forward declaration
84 mDNSlocal void VerifySigCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
85 mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv);
86 mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv);
87 mDNSlocal mStatus ValidateDS(DNSSECVerifier *dv);
88 mDNSlocal void DNSSECNegativeValidationCB(mDNS *const m, DNSSECVerifier *dv, CacheGroup *cg, ResourceRecord *answer, DNSSECStatus status);
89 mDNSlocal RRVerifier* CopyRRVerifier(RRVerifier *from);
90 mDNSlocal void FreeDNSSECAuthChainInfo(AuthChain *ac);
91
92 // Currently we use this to convert a RRVerifier to resource record so that we can
93 // use the standard DNS utility functions
94 LargeCacheRecord largerec;
95
96 // Verification is a recursive process. We arbitrarily limit to 10 just to be cautious which should be
97 // removed in the future.
98 #define MAX_RECURSE_COUNT   10
99
100 // TTL (in seconds) when the DNSSEC status is Bogus
101 #define RR_BOGUS_TTL        60
102
103 // RFC 4034 Appendix B: Get the keyid of a DNS KEY. It is not transmitted
104 // explicitly on the wire.
105 //
106 // Note: This just helps narrow down the list of keys to look at. It is possible
107 // for two DNS keys to have the same ID i.e., key ID is not a unqiue tag
108 //
109 // 1st argument - the RDATA part of the DNSKEY RR
110 // 2nd argument - the RDLENGTH
111 //
112 mDNSlocal mDNSu32 keytag(mDNSu8 *key, mDNSu32 keysize)
113 {
114     unsigned long ac;
115     unsigned int i;
116
117     // DST_ALG_RSAMD5 will be rejected automatically as the keytag
118     // is calculated wrongly
119
120     for (ac = 0, i = 0; i < keysize; ++i)
121         ac += (i & 1) ? key[i] : key[i] << 8;
122     ac += (ac >> 16) & 0xFFFF;
123     return ac & 0xFFFF;
124 }
125
126 mDNSexport int DNSMemCmp(const mDNSu8 *const m1, const mDNSu8 *const m2, int len)
127 {
128     int res;
129
130     res = mDNSPlatformMemCmp(m1, m2, len);
131     if (res != 0)
132         return (res < 0 ? -1 : 1);
133     return 0;
134 }
135
136 // RFC 4034:
137 //
138 // Section 6.1:
139 //
140 // For the purposes of DNS security, owner names are ordered by treating
141 // individual labels as unsigned left-justified octet strings.  The
142 // absence of a octet sorts before a zero value octet, and uppercase
143 // US-ASCII letters are treated as if they were lowercase US-ASCII
144 // letters.
145 //
146 // To compute the canonical ordering of a set of DNS names, start by
147 // sorting the names according to their most significant (rightmost)
148 // labels.  For names in which the most significant label is identical,
149 // continue sorting according to their next most significant label, and
150 // so forth.
151 //
152 // Returns 0 if the names are same
153 // Returns -1 if d1 < d2
154 // Returns  1 if d1 > d2
155 //
156 // subdomain is set if there is at least one label match (starting from the end)
157 // and d1 has more labels than d2 e.g., a.b.com is a subdomain of b.com
158 //
159 mDNSexport int DNSSECCanonicalOrder(const domainname *const d1, const domainname *const d2, int *subdomain)
160 {
161     int count, c1, c2;
162     int i, skip1, skip2;
163
164     c1 = CountLabels(d1);
165     skip1 = c1 - 1;
166     c2 = CountLabels(d2);
167     skip2 = c2 - 1;
168
169     if (subdomain) *subdomain = 0;
170
171     // Compare as many labels as possible starting from the rightmost
172     count = c1 < c2 ? c1 : c2;
173     for (i = count; i > 0; i--)
174     {
175         mDNSu8 *a, *b;
176         int j, len, lena, lenb;
177
178         a = (mDNSu8 *)SkipLeadingLabels(d1, skip1);
179         b = (mDNSu8 *)SkipLeadingLabels(d2, skip2);
180         lena = *a;
181         lenb = *b;
182         // Compare label by label. Note that "z" > "yak" because z > y, but z < za
183         // (lena - lenb check below) because 'za' has two characters. Hence compare the
184         // letters first and then compare the length of the label at the end.
185         len = lena < lenb ? lena : lenb;
186         a++; b++;
187         for (j = 0; j < len; j++)
188         {
189             mDNSu8 ac = *a++;
190             mDNSu8 bc = *b++;
191             if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
192             if (mDNSIsUpperCase(bc)) bc += 'a' - 'A';
193             if (ac != bc)
194             {
195                 verbosedebugf("DNSSECCanonicalOrder: returning ac %c, bc %c", ac, bc);
196                 return ((ac < bc) ? -1 : 1);
197             }
198         }
199         if ((lena - lenb) != 0)
200         {
201             verbosedebugf("DNSSECCanonicalOrder: returning lena %d lenb %d", lena, lenb);
202             return ((lena < lenb) ? -1 : 1);
203         }
204
205         // Continue with the next label
206         skip1--;
207         skip2--;
208     }
209     // We have compared label by label. Both of them are same if we are here.
210     //
211     // Two possibilities.
212     //
213     // 1) Both names have same number of labels. In that case, return zero.
214     // 2) The number of labels is not same. As zero label sorts before, names
215     //    with more number of labels is greater.
216
217     // a.b.com is a subdomain of b.com
218     if ((c1 > c2) && subdomain)
219         *subdomain = 1;
220
221     verbosedebugf("DNSSECCanonicalOrder: returning c1 %d c2 %d\n", c1, c2);
222     if (c1 != c2)
223         return ((c1 < c2) ? -1 : 1);
224     else
225         return 0;
226 }
227
228 // Initialize the question enough so that it can be answered from the cache using SameNameRecordAnswersQuestion or
229 // ResourceRecordAnswersQuestion.
230 mDNSexport void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname,
231                                    mDNSu16 qtype, mDNSQuestionCallback *callback, void *context)
232 {
233     debugf("InitializeQuestion: Called for %##s (%s)", qname->c, DNSTypeName(qtype));
234
235     if (question->ThisQInterval != -1) mDNS_StopQuery(m, question);
236
237     mDNS_SetupQuestion(question, InterfaceID, qname, qtype, callback, context);
238     question->qnamehash  = DomainNameHashValue(qname);
239     question->ValidatingResponse = mDNStrue;
240
241     // Need to hold the lock, as GetServerForQuestion (its callers) references m->timenow.
242     mDNS_Lock(m);
243     // We need to set the DNS server appropriately to match the question against the cache record.
244     // Though not all callers of this function need it, we always do it to keep it simple.
245     SetValidDNSServers(m, question);
246     question->qDNSServer = GetServerForQuestion(m, question);
247     mDNS_Unlock(m);
248
249     // Make it look like unicast
250     question->TargetQID = onesID;
251     question->TimeoutQuestion = 1;
252     question->ReturnIntermed = 1;
253     // SetupQuestion sets LongLived if qtype == PTR
254     question->LongLived = 0;
255 }
256
257 mDNSexport DNSSECVerifier *AllocateDNSSECVerifier(mDNS *const m, const domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID,
258     mDNSu8 ValidationRequired, DNSSECVerifierCallback dvcallback, mDNSQuestionCallback qcallback)
259 {
260     DNSSECVerifier *dv;
261
262     dv = (DNSSECVerifier *)mDNSPlatformMemAllocate(sizeof(DNSSECVerifier));
263     if (!dv) { LogMsg("AllocateDNSSECVerifier: ERROR!! memory alloc failed"); return mDNSNULL; }
264     mDNSPlatformMemZero(dv, sizeof(*dv));
265
266     LogDNSSEC("AllocateDNSSECVerifier called %p", dv);
267
268     // Remember the question's name and type so that when we are done processing all
269     // the verifications, we can trace the original question back
270     AssignDomainName(&dv->origName, name);
271     dv->origType = rrtype;
272     dv->InterfaceID = InterfaceID;
273     dv->DVCallback = dvcallback;
274     dv->q.ThisQInterval = -1;
275     ResetAuthChain(dv);
276     // These two are used for Insecure proof if we end up doing it.
277     // -Value of ValidationRequired so that we know whether this is a secure or insecure validation
278     // -InsecureProofDone tells us whether the proof has been done or not
279     dv->ValidationRequired = ValidationRequired;
280     dv->InsecureProofDone = 0;
281     dv->NumPackets = 0;
282     mDNS_Lock(m);
283     dv->StartTime = m->timenow;
284     mDNS_Unlock(m);
285     // The verifier's question has to be initialized as some of the callers assume it
286     InitializeQuestion(m, &dv->q, InterfaceID, name, rrtype, qcallback, dv);
287     return dv;
288 }
289
290 mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
291 {
292     RRVerifier *rvfrom, **rvto;
293     AuthChain **prev = mDNSNULL;
294     AuthChain *retac = mDNSNULL;
295     AuthChain *ac;
296
297
298     while (ae)
299     {
300         ac = mDNSPlatformMemAllocate(sizeof(AuthChain));
301         if (!ac)
302         {
303             LogMsg("AuthChainCopy: AuthChain alloc failure");
304             if (retac)
305                 FreeDNSSECAuthChainInfo(retac);
306             return mDNSfalse;
307         }
308
309         ac->next  = mDNSNULL;
310
311         if (!retac)
312             retac = ac;
313
314         rvfrom = ae->rrset;
315         rvto = &ac->rrset;
316         while (rvfrom && rvto)
317         {
318             *rvto = CopyRRVerifier(rvfrom);
319             rvfrom = rvfrom->next;
320             rvto = &((*rvto)->next);
321         }
322
323         rvfrom = ae->rrsig;
324         rvto = &ac->rrsig;
325         while (rvfrom && rvto)
326         {
327             *rvto = CopyRRVerifier(rvfrom);
328             rvfrom = rvfrom->next;
329             rvto = &((*rvto)->next);
330         }
331
332         rvfrom = ae->key;
333         rvto = &ac->key;
334         while (rvfrom && rvto)
335         {
336             *rvto = CopyRRVerifier(rvfrom);
337             rvfrom = rvfrom->next;
338             rvto = &((*rvto)->next);
339         }
340
341         if (prev)
342         {
343             *prev = ac;
344         }
345         prev = &(ac->next);
346         ae = ae->next;
347     }
348     return retac;
349 }
350
351 mDNSlocal void FreeDNSSECAuthChainInfo(AuthChain *ac)
352 {
353     RRVerifier *rrset;
354     RRVerifier *next;
355     AuthChain *acnext;
356
357     LogDNSSEC("FreeDNSSECAuthChainInfo: called");
358
359     while (ac)
360     {
361         acnext = ac->next;
362         rrset = ac->rrset;
363         while (rrset)
364         {
365             next = rrset->next;
366             mDNSPlatformMemFree(rrset);
367             rrset = next;
368         }
369         ac->rrset = mDNSNULL;
370
371         rrset = ac->rrsig;
372         while (rrset)
373         {
374             next = rrset->next;
375             mDNSPlatformMemFree(rrset);
376             rrset = next;
377         }
378         ac->rrsig = mDNSNULL;
379
380         rrset = ac->key;
381         while (rrset)
382         {
383             next = rrset->next;
384             mDNSPlatformMemFree(rrset);
385             rrset = next;
386         }
387         ac->key = mDNSNULL;
388
389         mDNSPlatformMemFree(ac);
390         ac = acnext;
391     }
392 }
393
394 mDNSlocal void FreeDNSSECAuthChain(DNSSECVerifier *dv)
395 {
396     if (dv->ac)
397     {
398         FreeDNSSECAuthChainInfo(dv->ac);
399         // if someone reuses the "dv", it will be initialized properly
400         ResetAuthChain(dv);
401     }
402     if (dv->saveac)
403     {
404         FreeDNSSECAuthChainInfo(dv->saveac);
405         dv->saveac = mDNSNULL;
406     }
407 }
408
409 mDNSlocal void FreeAuthChain(mDNS *const m, void *context)
410 {
411     AuthChain *ac = (AuthChain *)context;
412     (void) m; // unused
413
414     FreeDNSSECAuthChainInfo(ac);
415 }
416
417 mDNSlocal void FreeDNSSECVerifierRRSets(DNSSECVerifier *dv)
418 {
419     RRVerifier *rrset;
420     RRVerifier *next;
421
422     //debugdnssec("FreeDNSSECVerifierRRSets called %p", dv);
423     rrset = dv->rrset;
424     while (rrset)
425     {
426         next = rrset->next;
427         mDNSPlatformMemFree(rrset);
428         rrset = next;
429     }
430     dv->rrset = mDNSNULL;
431
432     rrset = dv->rrsig;
433     while (rrset)
434     {
435         next = rrset->next;
436         mDNSPlatformMemFree(rrset);
437         rrset = next;
438     }
439     dv->rrsig = mDNSNULL;
440
441     rrset = dv->key;
442     while (rrset)
443     {
444         next = rrset->next;
445         mDNSPlatformMemFree(rrset);
446         rrset = next;
447     }
448     dv->key = mDNSNULL;
449
450     rrset = dv->rrsigKey;
451     while (rrset)
452     {
453         next = rrset->next;
454         mDNSPlatformMemFree(rrset);
455         rrset = next;
456     }
457     dv->rrsigKey = mDNSNULL;
458
459     rrset = dv->ds;
460     while (rrset)
461     {
462         next = rrset->next;
463         mDNSPlatformMemFree(rrset);
464         rrset = next;
465     }
466     dv->ds = mDNSNULL;
467     rrset = dv->pendingNSEC;
468     while (rrset)
469     {
470         next = rrset->next;
471         mDNSPlatformMemFree(rrset);
472         rrset = next;
473     }
474     dv->pendingNSEC = mDNSNULL;
475 }
476
477 mDNSexport void FreeDNSSECVerifier(mDNS *const m, DNSSECVerifier *dv)
478 {
479     LogDNSSEC("FreeDNSSECVerifier called %p", dv);
480     if (dv->q.ThisQInterval != -1)
481         mDNS_StopQuery(m, &dv->q);
482     FreeDNSSECVerifierRRSets(dv);
483     if (dv->ctx)
484         AlgDestroy(dv->ctx);
485     if (dv->ac || dv->saveac)
486         FreeDNSSECAuthChain(dv);
487     if (dv->parent)
488     {
489         LogDNSSEC("FreeDNSSECVerifier freeing parent %p", dv->parent);
490         FreeDNSSECVerifier(m, dv->parent);
491     }
492     mDNSPlatformMemFree(dv);
493 }
494
495 mDNSlocal RRVerifier* CopyRRVerifier(RRVerifier *from)
496 {
497     RRVerifier *r;
498
499     r = mDNSPlatformMemAllocate(sizeof (RRVerifier) + from->rdlength);
500     if (!r)
501     {
502         LogMsg("CopyRRVerifier: memory failure");
503         return mDNSNULL;
504     }
505     mDNSPlatformMemCopy(r, from, sizeof(RRVerifier));
506     r->next = mDNSNULL;
507     r->rdata = (mDNSu8*) ((mDNSu8 *)r + sizeof(RRVerifier));
508     mDNSPlatformMemCopy(r->rdata, from->rdata, r->rdlength);
509     return r;
510 }
511
512 mDNSexport RRVerifier* AllocateRRVerifier(const ResourceRecord *const rr, mStatus *status)
513 {
514     RRVerifier *r;
515
516     r = mDNSPlatformMemAllocate(sizeof (RRVerifier) + rr->rdlength);
517     if (!r)
518     {
519         LogMsg("AllocateRRVerifier: memory failure");
520         *status = mStatus_NoMemoryErr;
521         return mDNSNULL;
522     }
523     r->next = mDNSNULL;
524     r->rrtype = rr->rrtype;
525     r->rrclass = rr->rrclass;
526     r->rroriginalttl = rr->rroriginalttl;
527     r->rdlength = rr->rdlength;
528     r->namehash = rr->namehash;
529     r->rdatahash = rr->rdatahash;
530     AssignDomainName(&r->name, rr->name);
531     r->rdata = (mDNSu8*) ((mDNSu8 *)r + sizeof(RRVerifier));
532
533     // When we parsed the DNS response in GeLargeResourceRecord, for some records, we parse them into
534     // host order so that the rest of the code does not have to bother with converting from network order
535     // to host order. For signature verification, we need them back in network order. For DNSSEC records
536     // like DNSKEY and DS, we just copy over the data both in GetLargeResourceRecord and putRData.
537
538     if (!putRData(mDNSNULL, r->rdata, r->rdata + rr->rdlength, rr))
539     {
540         LogMsg("AllocateRRVerifier: putRData failed");
541         *status = mStatus_BadParamErr;
542         return mDNSNULL;
543     }
544     *status = mStatus_NoError;
545     return r;
546 }
547
548 mDNSexport mStatus AddRRSetToVerifier(DNSSECVerifier *dv, const ResourceRecord *const rr, RRVerifier *rv, RRVerifierSet set)
549 {
550     RRVerifier *r;
551     RRVerifier **v;
552     mStatus status;
553
554     if (!rv)
555     {
556         r = AllocateRRVerifier(rr, &status);
557         if (!r) return status;
558     }
559     else
560         r = rv;
561
562     switch (set)
563     {
564     case RRVS_rr:
565         v = &dv->rrset;
566         break;
567     case RRVS_rrsig:
568         v = &dv->rrsig;
569         break;
570     case RRVS_key:
571         v = &dv->key;
572         break;
573     case RRVS_rrsig_key:
574         v = &dv->rrsigKey;
575         break;
576     case RRVS_ds:
577         v = &dv->ds;
578         break;
579     default:
580         LogMsg("AddRRSetToVerifier: ERROR!! default case %d", set);
581         return mStatus_BadParamErr;
582     }
583     while (*v)
584         v = &(*v)->next;
585     *v = r;
586     return mStatus_NoError;
587 }
588
589 // Validate the RRSIG. "type" tells which RRSIG that we are supposed to validate. We fetch RRSIG for
590 // the rrset (type is RRVS_rrsig) and RRSIG for the key (type is RRVS_rrsig_key).
591 mDNSexport void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const ResourceRecord *const rr)
592 {
593     RRVerifier *rv;
594     mDNSu32 currentTime;
595     rdataRRSig *rrsigRData = (rdataRRSig *)((mDNSu8 *)rr->rdata + sizeofRDataHeader);
596
597     if (type == RRVS_rrsig)
598     {
599         rv = dv->rrset;
600     }
601     else if (type == RRVS_rrsig_key)
602     {
603         rv = dv->key;
604     }
605     else
606     {
607         LogMsg("ValidateRRSIG: ERROR!! type not valid %d", type);
608         return;
609     }
610
611     // RFC 4035:
612     // For each authoritative RRset in a signed zone, there MUST be at least
613     // one RRSIG record that meets the following requirements:
614     //
615     // RRSet is defined by same name, class and type
616     //
617     // 1. The RRSIG RR and the RRset MUST have the same owner name and the same class.
618     if (!SameDomainName(&rv->name, rr->name) || (rr->rrclass != rv->rrclass))
619     {
620         debugdnssec("ValidateRRSIG: name mismatch or class mismatch");
621         return;
622     }
623
624     // 2. The RRSIG RR's Type Covered field MUST equal the RRset's type.
625     if ((swap16(rrsigRData->typeCovered)) != rv->rrtype)
626     {
627         debugdnssec("ValidateRRSIG: typeCovered mismatch rrsig %d, rr type %d", swap16(rrsigRData->typeCovered), rv->rrtype);
628         return;
629     }
630
631     // 3. The number of labels in the RRset owner name MUST be greater than or equal
632     //    to the value in the RRSIG RR's Labels field.
633     if (rrsigRData->labels > CountLabels(&rv->name))
634     {
635         debugdnssec("ValidateRRSIG: labels count problem rrsig %d, rr %d", rrsigRData->labels, CountLabels(&rv->name));
636         return;
637     }
638
639     // 4. The RRSIG RR's Signer's Name field MUST be the name of the zone that contains
640     //    the RRset. For a stub resolver, this can't be done in a secure way. Hence we
641     //    do it this way (discussed in dnsext mailing list)
642     switch (rv->rrtype)
643     {
644     case kDNSType_NS:
645     case kDNSType_SOA:
646     case kDNSType_DNSKEY:
647         //Signed by the owner
648         if (!SameDomainName(&rv->name, (domainname *)&rrsigRData->signerName))
649         {
650             debugdnssec("ValidateRRSIG: Signer Name does not match the record name for %s", DNSTypeName(rv->rrtype));
651             return;
652         }
653         break;
654     case kDNSType_DS:
655         // Should be signed by the parent
656         if (SameDomainName(&rv->name, (domainname *)&rrsigRData->signerName))
657         {
658             debugdnssec("ValidateRRSIG: Signer Name matches the record name for %s", DNSTypeName(rv->rrtype));
659             return;
660         }
661     // FALLTHROUGH
662     default:
663     {
664         int c1 = CountLabels(&rv->name);
665         int c2 = CountLabels((domainname *)&rrsigRData->signerName);
666         if (c1 < c2)
667         {
668             debugdnssec("ValidateRRSIG: Signer Name not a subdomain label count %d < %d ", c1, c2);
669             return;
670         }
671         domainname *d = (domainname *)SkipLeadingLabels(&rv->name, c1 - c2);
672         if (!SameDomainName(d, (domainname *)&rrsigRData->signerName))
673         {
674             debugdnssec("ValidateRRSIG: Signer Name not a subdomain");
675             return;
676         }
677         break;
678     }
679     }
680
681     // 5. The validator's notion of the current time MUST be less than or equal to the
682     //    time listed in the RRSIG RR's Expiration field.
683     //
684     // 6. The validator's notion of the current time MUST be greater than or equal to the
685     //    time listed in the RRSIG RR's Inception field.
686     currentTime = mDNSPlatformUTC();
687
688     if (DNS_SERIAL_LT(swap32(rrsigRData->sigExpireTime), currentTime))
689     {
690         LogDNSSEC("ValidateRRSIG: Expired: currentTime %d, ExpireTime %d", (int)currentTime,
691                   swap32((int)rrsigRData->sigExpireTime));
692         return;
693     }
694     if (DNS_SERIAL_LT(currentTime, swap32(rrsigRData->sigInceptTime)))
695     {
696         LogDNSSEC("ValidateRRSIG: Future: currentTime %d, InceptTime %d", (int)currentTime,
697                   swap32((int)rrsigRData->sigInceptTime));
698         return;
699     }
700
701     if (AddRRSetToVerifier(dv, rr, mDNSNULL, type) != mStatus_NoError)
702     {
703         LogMsg("ValidateRRSIG: ERROR!! cannot allocate RRSet");
704         return;
705     }
706 }
707
708 mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
709 {
710     CacheGroup *cg;
711     CacheRecord *cr;
712     RRVerifier *rv;
713     mDNSBool expectRRSIG = mDNSfalse;
714
715     *negcr = mDNSNULL;
716     if (!dv->rrset)
717     {
718         LogMsg("CheckRRSIGForRRSet: ERROR!! rrset NULL for origName %##s (%s)", dv->origName.c,
719                DNSTypeName(dv->origType));
720         return mStatus_BadParamErr;
721     }
722
723     rv = dv->rrset;
724     cg = CacheGroupForName(m, rv->namehash, &rv->name);
725     if (!cg)
726     {
727         debugdnssec("CheckRRSIGForRRSet: cg null");
728         return mStatus_NoSuchRecord;
729     }
730
731     for (cr=cg->members; cr; cr=cr->next)
732     {
733         debugdnssec("CheckRRSIGForRRSet: checking the validity of rrsig");
734         if (cr->resrec.rrtype != kDNSType_RRSIG)
735         {
736             // Check to see if we should expect RRSIGs for the type that we are looking for.
737             // We would expect RRSIGs, if we had previously issued the question with the
738             // EDNS0/DOK bit set.
739             if (cr->resrec.rrtype == dv->rrset->rrtype)
740             {
741                 expectRRSIG = cr->CRDNSSECQuestion;
742                 LogDNSSEC("CheckRRSIGForRRSet: %s RRSIG for %s", (expectRRSIG ? "Expecting" : "Not Expecting"), CRDisplayString(m, cr));
743             }
744             continue;
745         }
746         if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
747         {
748             if (!(*negcr))
749             {
750                 LogDNSSEC("CheckRRSIGForRRSet: Negative cache record %s encountered for %##s (%s)", CRDisplayString(m, cr),
751                           rv->name.c, DNSTypeName(rv->rrtype));
752                 *negcr = cr;
753             }
754             else
755             {
756                 LogMsg("CheckRRSIGForRRSet: ERROR!! Negative cache record %s already set for %##s (%s)", CRDisplayString(m, cr),
757                        rv->name.c, DNSTypeName(rv->rrtype));
758             }
759             continue;
760         }
761         ValidateRRSIG(dv, RRVS_rrsig, &cr->resrec);
762     }
763     if (*negcr && dv->rrsig)
764     {
765         // Encountered both RRSIG and negative CR
766         LogMsg("CheckRRSIGForRRSet: ERROR!! Encountered negative cache record %s and RRSIG for %##s (%s)",
767                CRDisplayString(m, *negcr), rv->name.c, DNSTypeName(rv->rrtype));
768         return mStatus_BadParamErr;
769     }
770     // If we can't find RRSIGs, but we find a negative response then we need to validate that
771     // which the caller will do it. Otherwise, if we should be expecting RRSIGs to be in the
772     // cache already, then return error.
773     if (dv->rrsig || *negcr)
774         return mStatus_NoError;
775     else if (expectRRSIG)
776         return mStatus_BadParamErr;
777     else
778         return mStatus_NoSuchRecord;
779 }
780
781 mDNSlocal void CheckOneKeyForRRSIG(DNSSECVerifier *dv, const ResourceRecord *const rr)
782 {
783     rdataRRSig *rrsig;
784
785     if (!dv->rrsig)
786     {
787         LogMsg("CheckOneKeyForRRSIG: ERROR!! rrsig NULL");
788         return;
789     }
790     rrsig = (rdataRRSig *)dv->rrsig->rdata;
791     if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
792     {
793         debugdnssec("CheckOneKeyForRRSIG: name mismatch");
794         return;
795     }
796
797     // We store all the keys including the ZSK and KSK and use them appropriately
798     // later
799     if (AddRRSetToVerifier(dv, rr, mDNSNULL, RRVS_key) != mStatus_NoError)
800     {
801         LogMsg("CheckOneKeyForRRSIG: ERROR!! cannot allocate RRSet");
802         return;
803     }
804 }
805
806 mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
807 {
808     mDNSu32 namehash;
809     CacheGroup *cg;
810     CacheRecord *cr;
811     rdataRRSig *rrsig;
812     domainname *name;
813
814     *negcr = mDNSNULL;
815     if (!dv->rrsig)
816     {
817         LogMsg("CheckKeyForRRSIG: ERROR!! rrsig NULL");
818         return mStatus_BadParamErr;
819     }
820
821     // Signer name should be the same on all rrsig ??
822     rrsig = (rdataRRSig *)dv->rrsig->rdata;
823     name = (domainname *)&rrsig->signerName;
824
825     namehash = DomainNameHashValue(name);
826     cg = CacheGroupForName(m, namehash, name);
827     if (!cg)
828     {
829         debugdnssec("CheckKeyForRRSIG: cg null for %##s", name->c);
830         return mStatus_NoSuchRecord;
831     }
832
833     for (cr=cg->members; cr; cr=cr->next)
834     {
835         if (cr->resrec.rrtype != kDNSType_DNSKEY) continue;
836         if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
837         {
838             if (!(*negcr))
839             {
840                 LogDNSSEC("CheckKeyForRRSIG: Negative cache record %s encountered for %##s (DNSKEY)", CRDisplayString(m, cr),
841                           name->c);
842                 *negcr = cr;
843             }
844             else
845             {
846                 LogMsg("CheckKeyForRRSIG: ERROR!! Negative cache record %s already set for %##s (DNSKEY)", CRDisplayString(m, cr),
847                        name->c);
848             }
849             continue;
850         }
851         debugdnssec("CheckKeyForRRSIG: checking the validity of key record");
852         CheckOneKeyForRRSIG(dv, &cr->resrec);
853     }
854     if (*negcr && dv->key)
855     {
856         // Encountered both RRSIG and negative CR
857         LogMsg("CheckKeyForRRSIG: ERROR!! Encountered negative cache record %s and DNSKEY for %##s",
858                CRDisplayString(m, *negcr), name->c);
859         return mStatus_BadParamErr;
860     }
861     if (dv->key || *negcr)
862         return mStatus_NoError;
863     else
864         return mStatus_NoSuchRecord;
865 }
866
867 mDNSlocal void CheckOneRRSIGForKey(DNSSECVerifier *dv, const ResourceRecord *const rr)
868 {
869     rdataRRSig *rrsig;
870     if (!dv->rrsig)
871     {
872         LogMsg("CheckOneRRSIGForKey: ERROR!! rrsig NULL");
873         return;
874     }
875     rrsig = (rdataRRSig *)dv->rrsig->rdata;
876     if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
877     {
878         debugdnssec("CheckOneRRSIGForKey: name mismatch");
879         return;
880     }
881     ValidateRRSIG(dv, RRVS_rrsig_key, rr);
882 }
883
884 mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
885 {
886     mDNSu32 namehash;
887     CacheGroup *cg;
888     CacheRecord *cr;
889     rdataRRSig *rrsig;
890     domainname *name;
891     mDNSBool expectRRSIG = mDNSfalse;
892
893     *negcr = mDNSNULL;
894     if (!dv->rrsig)
895     {
896         LogMsg("CheckRRSIGForKey: ERROR!! rrsig NULL");
897         return mStatus_BadParamErr;
898     }
899     if (!dv->key)
900     {
901         LogMsg("CheckRRSIGForKey:  ERROR!! key NULL");
902         return mStatus_BadParamErr;
903     }
904     rrsig = (rdataRRSig *)dv->rrsig->rdata;
905     name = (domainname *)&rrsig->signerName;
906
907     namehash = DomainNameHashValue(name);
908     cg = CacheGroupForName(m, namehash, name);
909     if (!cg)
910     {
911         debugdnssec("CheckRRSIGForKey: cg null %##s", name->c);
912         return mStatus_NoSuchRecord;
913     }
914     for (cr=cg->members; cr; cr=cr->next)
915     {
916         if (cr->resrec.rrtype != kDNSType_RRSIG)
917         {
918             // Check to see if we should expect RRSIGs for the DNSKEY record that we are
919             // looking for. We would expect RRSIGs, if we had previously issued the question
920             // with the EDNS0/DOK bit set.
921             if (cr->resrec.rrtype == kDNSType_DNSKEY)
922             {
923                 expectRRSIG = cr->CRDNSSECQuestion;
924                 LogDNSSEC("CheckRRSIGForKey: %s RRSIG for %s", (expectRRSIG ? "Expecting" : "Not Expecting"), CRDisplayString(m, cr));
925             }
926             continue;
927         }
928         if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
929         {
930             if (!(*negcr))
931             {
932                 LogDNSSEC("CheckRRSIGForKey: Negative cache record %s encountered for %##s (RRSIG)", CRDisplayString(m, cr),
933                           name->c);
934                 *negcr = cr;
935             }
936             else
937             {
938                 LogMsg("CheckRRSIGForKey: ERROR!! Negative cache record %s already set for %##s (RRSIG)", CRDisplayString(m, cr),
939                        name->c);
940             }
941             continue;
942         }
943         debugdnssec("CheckRRSIGForKey: checking the validity of rrsig");
944         CheckOneRRSIGForKey(dv, &cr->resrec);
945     }
946     if (*negcr && dv->rrsigKey)
947     {
948         // Encountered both RRSIG and negative CR
949         LogMsg("CheckRRSIGForKey: ERROR!! Encountered negative cache record %s and DNSKEY for %##s",
950                CRDisplayString(m, *negcr), name->c);
951         return mStatus_BadParamErr;
952     }
953     // If we can't find RRSIGs, but we find a negative response then we need to validate that
954     // which the caller will do it. Finally, make sure that we are not expecting RRSIGS.
955     if (dv->rrsigKey || *negcr)
956         return mStatus_NoError;
957     else if (expectRRSIG)
958         return mStatus_BadParamErr;
959     else
960         return mStatus_NoSuchRecord;
961 }
962
963 mDNSlocal void CheckOneDSForKey(DNSSECVerifier *dv, const ResourceRecord *const rr)
964 {
965     mDNSu16 tag;
966     rdataDS *DS;
967     RRVerifier *keyv;
968     rdataDNSKey *key;
969     rdataRRSig *rrsig;
970
971     if (!dv->rrsig)
972     {
973         LogMsg("CheckOneDSForKey: ERROR!! rrsig NULL");
974         return;
975     }
976     rrsig = (rdataRRSig *)dv->rrsig->rdata;
977     DS = (rdataDS *)((mDNSu8 *)rr->rdata + sizeofRDataHeader);
978
979     if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
980     {
981         debugdnssec("CheckOneDSForKey: name mismatch");
982         return;
983     }
984     for (keyv = dv->key; keyv; keyv = keyv->next)
985     {
986         key = (rdataDNSKey *)keyv->rdata;
987         tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
988         if (tag != swap16(DS->keyTag))
989         {
990             debugdnssec("CheckOneDSForKey: keyTag mismatch keyTag %d, DStag %d", tag, swap16(DS->keyTag));
991             continue;
992         }
993         if (key->alg != DS->alg)
994         {
995             debugdnssec("CheckOneDSForKey: alg mismatch key alg%d, DS alg %d", key->alg, swap16(DS->alg));
996             continue;
997         }
998         if (AddRRSetToVerifier(dv, rr, mDNSNULL, RRVS_ds) != mStatus_NoError)
999         {
1000             debugdnssec("CheckOneDSForKey: cannot allocate RRSet");
1001         }
1002     }
1003 }
1004
1005 mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
1006 {
1007     mDNSu32 namehash;
1008     CacheGroup *cg;
1009     CacheRecord *cr;
1010     rdataRRSig *rrsig;
1011     domainname *name;
1012
1013     *negcr = mDNSNULL;
1014     if (!dv->rrsig)
1015     {
1016         LogMsg("CheckDSForKey: ERROR!! rrsig NULL");
1017         return mStatus_BadParamErr;
1018     }
1019     if (!dv->key)
1020     {
1021         LogMsg("CheckDSForKey: ERROR!! key NULL");
1022         return mStatus_BadParamErr;
1023     }
1024     rrsig = (rdataRRSig *)dv->rrsig->rdata;
1025     name = (domainname *)&rrsig->signerName;
1026     namehash = DomainNameHashValue(name);
1027     cg = CacheGroupForName(m, namehash, name);
1028     if (!cg)
1029     {
1030         debugdnssec("CheckDSForKey: cg null for %s", name->c);
1031         return mStatus_NoSuchRecord;
1032     }
1033     for (cr=cg->members; cr; cr=cr->next)
1034     {
1035         if (cr->resrec.rrtype != kDNSType_DS) continue;
1036         if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
1037         {
1038             if (!(*negcr))
1039             {
1040                 LogDNSSEC("CheckDSForKey: Negative cache record %s encountered for %##s (DS)", CRDisplayString(m, cr),
1041                           name->c);
1042                 *negcr = cr;
1043             }
1044             else
1045             {
1046                 LogMsg("CheckDSForKey: ERROR!! Negative cache record %s already set for %##s (DS)", CRDisplayString(m, cr),
1047                        name->c);
1048             }
1049             continue;
1050         }
1051         CheckOneDSForKey(dv, &cr->resrec);
1052     }
1053     if (*negcr && dv->ds)
1054     {
1055         // Encountered both RRSIG and negative CR
1056         LogMsg("CheckDSForKey: ERROR!! Encountered negative cache record %s and DS for %##s",
1057                CRDisplayString(m, *negcr), name->c);
1058         return mStatus_BadParamErr;
1059     }
1060     if (dv->ds || *negcr)
1061         return mStatus_NoError;
1062     else
1063         return mStatus_NoSuchRecord;
1064 }
1065
1066 // It returns mDNStrue if we have all the rrsets for verification and mDNSfalse otherwise.
1067 mDNSlocal mDNSBool GetAllRRSetsForVerification(mDNS *const m, DNSSECVerifier *dv)
1068 {
1069     mStatus err;
1070     CacheRecord *negcr;
1071     rdataRRSig *rrsig;
1072
1073     if (!dv->rrset)
1074     {
1075         LogMsg("GetAllRRSetsForVerification: ERROR!! rrset NULL");
1076         dv->DVCallback(m, dv, DNSSEC_Bogus);
1077         return mDNSfalse;
1078     }
1079
1080     if (dv->next == RRVS_done) return mDNStrue;
1081
1082     debugdnssec("GetAllRRSetsForVerification: next %d", dv->next);
1083     switch (dv->next)
1084     {
1085     case RRVS_rrsig:
1086         // If we can't find the RRSIG for the rrset, re-issue the query.
1087         //
1088         // NOTE: It is possible that the cache might answer partially e.g., RRSIGs match qtype but the
1089         // whole set is not there. In that case the validation will fail. Ideally we should flush the
1090         // cache and reissue the query (TBD).
1091         err = CheckRRSIGForRRSet(m, dv, &negcr);
1092         if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
1093         {
1094             dv->DVCallback(m, dv, DNSSEC_Bogus);
1095             return mDNSfalse;
1096         }
1097         // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
1098         // looks in "dv->q" for the proof. Note that we have to use currQtype as the response could be
1099         // a CNAME and dv->rrset->rrtype would be set to CNAME and not the original question type that
1100         // resulted in CNAME.
1101         InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->rrset->name, dv->currQtype, VerifySigCallback, dv);
1102         // We may not have the NSECS if the previous query was a non-DNSSEC query
1103         if (negcr && negcr->nsec)
1104         {
1105             ValidateWithNSECS(m, dv, negcr);
1106             return mDNSfalse;
1107         }
1108
1109         dv->next = RRVS_key;
1110         if (!dv->rrsig)
1111         {
1112             // We already found the rrset to verify. Ideally we should just issue the query for the RRSIG. Unfortunately,
1113             // that does not work well as the response may not contain the RRSIG whose typeCovered matches the
1114             // rrset->rrtype (recursive server returns what is in its cache). Hence, we send the original query with the
1115             // DO bit set again to get the RRSIG. Normally this would happen if there was question which did not require
1116             // DNSSEC validation (ValidationRequied = 0) populated the cache and later when the ValidationRequired question
1117             // comes along, we need to get the RRSIGs. If we started off with ValidationRequired question we would have
1118             // already set the DO bit and not able to get RRSIGs e.g., bad CPE device, we would reissue the query here
1119             // again once more.
1120             //
1121             // Also, if it is a wildcard expanded answer, we need to issue the query with the original type for it to
1122             // elicit the right NSEC records. Just querying for RRSIG alone is not sufficient.
1123             //
1124             // Note: For this to work, the core needs to deliver RRSIGs when they are added to the cache even if the
1125             // "qtype" is not RRSIG.
1126             debugdnssec("GetAllRRSetsForVerification: Fetching RRSIGS for RRSET");
1127             dv->NumPackets++;
1128             mDNS_StartQuery(m, &dv->q);
1129             return mDNSfalse;
1130         }
1131         // if we found the RRSIG, then fall through to find the DNSKEY
1132     case RRVS_key:
1133         err = CheckKeyForRRSIG(m, dv, &negcr);
1134         if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
1135         {
1136             dv->DVCallback(m, dv, DNSSEC_Bogus);
1137             return mDNSfalse;
1138         }
1139         // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
1140         // looks in "dv->q" for the proof.
1141         rrsig = (rdataRRSig *)dv->rrsig->rdata;
1142         InitializeQuestion(m, &dv->q, dv->InterfaceID, (domainname *)&rrsig->signerName, kDNSType_DNSKEY, VerifySigCallback, dv);
1143         // We may not have the NSECS if the previous query was a non-DNSSEC query
1144         if (negcr && negcr->nsec)
1145         {
1146             ValidateWithNSECS(m, dv, negcr);
1147             return mDNSfalse;
1148         }
1149
1150         dv->next = RRVS_rrsig_key;
1151         if (!dv->key)
1152         {
1153             debugdnssec("GetAllRRSetsForVerification: Fetching DNSKEY for RRSET");
1154             dv->NumPackets++;
1155             mDNS_StartQuery(m, &dv->q);
1156             return mDNSfalse;
1157         }
1158     // if we found the DNSKEY, then fall through to find the RRSIG for the DNSKEY
1159     case RRVS_rrsig_key:
1160         err = CheckRRSIGForKey(m, dv, &negcr);
1161         // if we are falling through, then it is okay if we don't find the record
1162         if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
1163         {
1164             dv->DVCallback(m, dv, DNSSEC_Bogus);
1165             return mDNSfalse;
1166         }
1167         // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
1168         // looks in "dv->q" for the proof.
1169         rrsig = (rdataRRSig *)dv->rrsig->rdata;
1170         InitializeQuestion(m, &dv->q, dv->InterfaceID, (domainname *)&rrsig->signerName, kDNSType_DNSKEY, VerifySigCallback, dv);
1171         // We may not have the NSECS if the previous query was a non-DNSSEC query
1172         if (negcr && negcr->nsec)
1173         {
1174             ValidateWithNSECS(m, dv, negcr);
1175             return mDNSfalse;
1176         }
1177         dv->next = RRVS_ds;
1178         debugdnssec("GetAllRRSetsForVerification: RRVS_rrsig_key %p", dv->rrsigKey);
1179         if (!dv->rrsigKey)
1180         {
1181             debugdnssec("GetAllRRSetsForVerification: Fetching RRSIGS for DNSKEY");
1182             dv->NumPackets++;
1183             mDNS_StartQuery(m, &dv->q);
1184             return mDNSfalse;
1185         }
1186     // if we found RRSIG for the DNSKEY, then fall through to find the DS
1187     case RRVS_ds:
1188     {
1189         domainname *qname;
1190         rrsig = (rdataRRSig *)dv->rrsig->rdata;
1191         qname = (domainname *)&rrsig->signerName;
1192
1193         err = CheckDSForKey(m, dv, &negcr);
1194         if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
1195         {
1196             dv->DVCallback(m, dv, DNSSEC_Bogus);
1197             return mDNSfalse;
1198         }
1199         // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
1200         // looks in "dv->q" for the proof.
1201         InitializeQuestion(m, &dv->q, dv->InterfaceID, qname, kDNSType_DS, VerifySigCallback, dv);
1202         // We may not have the NSECS if the previous query was a non-DNSSEC query
1203         if (negcr && negcr->nsec)
1204         {
1205             ValidateWithNSECS(m, dv, negcr);
1206             return mDNSfalse;
1207         }
1208         dv->next = RRVS_done;
1209         // If we have a trust anchor, then don't bother looking up the DS record
1210         if (!dv->ds && !TrustedKeyPresent(m, dv))
1211         {
1212             // There is no DS for the root. Hence, if we don't have the trust
1213             // anchor for root, just fail.
1214             if (SameDomainName(qname, (const domainname *)"\000"))
1215             {
1216                 LogDNSSEC("GetAllRRSetsForVerification: Reached root");
1217                 dv->DVCallback(m, dv, DNSSEC_Bogus);
1218                 return mDNSfalse;
1219             }
1220             debugdnssec("GetAllRRSetsForVerification: Fetching DS");
1221             dv->NumPackets++;
1222             mDNS_StartQuery(m, &dv->q);
1223             return mDNSfalse;
1224         }
1225         else
1226         {
1227             debugdnssec("GetAllRRSetsForVerification: Skipped fetching the DS");
1228             return mDNStrue;
1229         }
1230     }
1231     default:
1232         LogMsg("GetAllRRSetsForVerification: ERROR!! unknown next %d", dv->next);
1233         dv->DVCallback(m, dv, DNSSEC_Bogus);
1234         return mDNSfalse;
1235     }
1236 }
1237
1238 #ifdef DNSSEC_DEBUG
1239 mDNSlocal void PrintFixedSignInfo(rdataRRSig *rrsig, domainname *signerName, int sigNameLen, mDNSu8 *fixedPart, int fixedPartLen)
1240 {
1241     int j;
1242     char buf[RRSIG_FIXED_SIZE *3 + 1]; // 3 bytes count for %2x + 1 and the one byte for null at the end
1243     char sig[sigNameLen * 3 + 1];
1244     char fp[fixedPartLen * 3 + 1];
1245     int length;
1246
1247     length = 0;
1248     for (j = 0; j < RRSIG_FIXED_SIZE; j++)
1249         length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", ((mDNSu8 *)rrsig)[j]);
1250     LogMsg("RRSIG(%d) %s", RRSIG_FIXED_SIZE, buf);
1251
1252
1253     length = 0;
1254     for (j = 0; j < sigNameLen; j++)
1255         length += mDNS_snprintf(sig+length, sizeof(sig) - length - 1, "%2x ", signerName->c[j]);
1256     LogMsg("SIGNAME(%d) %s", sigNameLen, sig);
1257
1258     length = 0;
1259     for (j = 0; j < fixedPartLen; j++)
1260         length += mDNS_snprintf(fp+length, sizeof(fp) - length - 1, "%2x ", fixedPart[j]);
1261     LogMsg("fixedPart(%d) %s", fixedPartLen, fp);
1262 }
1263
1264 mDNSlocal void PrintVarSignInfo(mDNSu16 rdlen, mDNSu8 *rdata)
1265 {
1266     unsigned int j;
1267     mDNSu8 *r;
1268     unsigned int blen = swap16(rdlen);
1269     char buf[blen * 3 + 1]; // 3 bytes count for %2x + 1 and the one byte for null at the end
1270     int length;
1271
1272     length = 0;
1273
1274     r = (mDNSu8 *)&rdlen;
1275     for (j = 0; j < sizeof(mDNSu16); j++)
1276         length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", r[j]);
1277     LogMsg("RDLENGTH(%d) %s", sizeof(mDNSu16), buf);
1278
1279     length = 0;
1280     for (j = 0; j < blen; j++)
1281         length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", rdata[j]);
1282     LogMsg("RDATA(%d) %s", blen, buf);
1283 }
1284 #else
1285 mDNSlocal void PrintVarSignInfo(mDNSu16 rdlen, mDNSu8 *rdata)
1286 {
1287     (void)rdlen;
1288     (void)rdata;
1289 }
1290 mDNSlocal void PrintFixedSignInfo(rdataRRSig *rrsig, domainname *signerName, int sigNameLen, mDNSu8 *fixedPart, int fixedPartLen)
1291 {
1292     (void)rrsig;
1293     (void)signerName;
1294     (void)sigNameLen;
1295     (void)fixedPart;
1296     (void)fixedPartLen;
1297 }
1298 #endif
1299
1300 // Used for RDATA comparison
1301 typedef struct
1302 {
1303     mDNSu16 rdlength;
1304     mDNSu16 rrtype;
1305     mDNSu8 *rdata;
1306 } rdataComp;
1307
1308 mDNSlocal int rdata_compare(mDNSu8 *const rdata1, mDNSu8 *const rdata2, int rdlen1, int rdlen2)
1309 {
1310     int len;
1311     int ret;
1312
1313     len = (rdlen1 < rdlen2) ? rdlen1 : rdlen2;
1314
1315     ret = DNSMemCmp(rdata1, rdata2, len);
1316     if (ret != 0) return ret;
1317
1318     // RDATA is same at this stage. Consider them equal if they are of same length. Otherwise
1319     // decide based on their lengths.
1320     return ((rdlen1 == rdlen2) ? 0 : (rdlen1 < rdlen2) ? -1 : 1);
1321 }
1322
1323 mDNSlocal int name_compare(mDNSu8 *const rdata1, mDNSu8 *const rdata2, int rdlen1, int rdlen2)
1324 {
1325     domainname *n1 = (domainname *)rdata1;
1326     domainname *n2 = (domainname *)rdata2;
1327     mDNSu8 *a = n1->c;
1328     mDNSu8 *b = n2->c;
1329     int count, c1, c2;
1330     int i, j, len;
1331
1332     c1 = CountLabels(n1);
1333     c2 = CountLabels(n2);
1334
1335     count = c1 < c2 ? c1 : c2;
1336
1337     // We can't use SameDomainName as we need to know exactly which is greater/smaller
1338     // for sorting purposes. Hence, we need to compare label by label
1339     for (i = 0; i < count; i++)
1340     {
1341         // Are the lengths same ?
1342         if (*a != *b)
1343         {
1344             debugdnssec("compare_name: returning c1 %d, c2 %d", *a, *b);
1345             return ((*a < *b) ? -1 : 1);
1346         }
1347         len = *a;
1348         rdlen1 -= (len + 1);
1349         rdlen2 -= (len + 1);
1350         if (rdlen1 < 0 || rdlen2 < 0)
1351         {
1352             LogMsg("name_compare: ERROR!! not enough data rdlen1 %d, rdlen2 %d", rdlen1, rdlen2);
1353             return -1;
1354         }
1355         a++; b++;
1356         for (j = 0; j < len; j++)
1357         {
1358             mDNSu8 ac = *a++;
1359             mDNSu8 bc = *b++;
1360             if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
1361             if (mDNSIsUpperCase(bc)) bc += 'a' - 'A';
1362             if (ac != bc)
1363             {
1364                 debugdnssec("compare_name: returning ac %c, bc %c", ac, bc);
1365                 return ((ac < bc) ? -1 : 1);
1366             }
1367         }
1368     }
1369
1370     return 0;
1371 }
1372
1373 mDNSlocal int srv_compare(rdataComp *const r1, rdataComp *const r2)
1374 {
1375     int res;
1376     int length1, length2;
1377
1378     length1 = r1->rdlength;
1379     length2 = r2->rdlength;
1380     // We should have at least priority, weight, port plus 1 byte
1381     if (length1 < 7 || length2 < 7)
1382     {
1383         LogMsg("srv_compare: ERROR!! Length smaller than 7 bytes");
1384         return -1;
1385     }
1386     // Compare priority, weight and port
1387     res = DNSMemCmp(r1->rdata, r2->rdata, 6);
1388     if (res != 0) return res;
1389     length1 -= 6;
1390     length2 -= 6;
1391     return (name_compare(r1->rdata + 6, r2->rdata + 6, length1, length2));
1392 }
1393
1394 mDNSlocal int tsig_compare(rdataComp *const r1, rdataComp *const r2)
1395 {
1396     int offset1, offset2;
1397     int length1, length2;
1398     int res, dlen;
1399
1400     offset1 = offset2 = 0;
1401     length1 = r1->rdlength;
1402     length2 = r2->rdlength;
1403
1404     // we should have at least one byte to start with
1405     if (length1 < 1 || length2 < 1)
1406     {
1407         LogMsg("sig_compare: Length smaller than 18 bytes");
1408         return -1;
1409     }
1410
1411     res = name_compare(r1->rdata, r2->rdata, length1, length2);
1412     if (res != 0) return res;
1413
1414     dlen = DomainNameLength((domainname *)r1->rdata);
1415     offset1 += dlen;
1416     offset2 += dlen;
1417     length1 -= dlen;
1418     length2 -= dlen;
1419
1420     if (length1 <= 1 || length2 <= 1)
1421     {
1422         LogMsg("tsig_compare: data too small to compare length1 %d, length2 %d", length1, length2);
1423         return -1;
1424     }
1425
1426     return (rdata_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2));
1427 }
1428
1429 // Compares types that conform to : <length><Value>
1430 mDNSlocal int lenval_compare(mDNSu8 *d1, mDNSu8 *d2, int *len1, int *len2, int rem1, int rem2)
1431 {
1432     int len;
1433     int res;
1434
1435     if (rem1 <= 1 || rem2 <= 1)
1436     {
1437         LogMsg("lenval_compare: data too small to compare length1 %d, length2 %d", rem1, rem2);
1438         return -1;
1439     }
1440     *len1 = (int)d1[0];
1441     *len2 = (int)d2[0];
1442     len = (*len1 < *len2 ? *len1 : *len2);
1443     res = DNSMemCmp(d1, d2, len + 1);
1444     return res;
1445 }
1446
1447 // RFC 2915: Order (2) Preference(2) and variable length: Flags Service Regexp Replacement
1448 mDNSlocal int naptr_compare(rdataComp *const r1, rdataComp *const r2)
1449 {
1450     mDNSu8 *d1 = r1->rdata;
1451     mDNSu8 *d2 = r2->rdata;
1452     int len1, len2, res;
1453     int length1, length2;
1454
1455     length1 = r1->rdlength;
1456     length2 = r2->rdlength;
1457
1458     // Order, Preference plus at least 1 byte
1459     if (length1 < 5 || length2 < 5)
1460     {
1461         LogMsg("naptr_compare: Length smaller than 18 bytes");
1462         return -1;
1463     }
1464     // Compare order and preference
1465     res = DNSMemCmp(d1, d2, 4);
1466     if (res != 0) return res;
1467
1468     d1 += 4;
1469     d2 += 4;
1470     length1 -= 4;
1471     length2 -= 4;
1472
1473     // Compare Flags (including the length byte)
1474     res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1475     if (res != 0) return res;
1476     d1 += (len1 + 1);
1477     d2 += (len2 + 1);
1478     length1 -= (len1 + 1);
1479     length2 -= (len2 + 1);
1480
1481     // Compare Service (including the length byte)
1482     res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1483     if (res != 0) return res;
1484     d1 += (len1 + 1);
1485     d2 += (len2 + 1);
1486     length1 -= (len1 + 1);
1487     length2 -= (len2 + 1);
1488
1489     // Compare regexp (including the length byte)
1490     res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1491     if (res != 0) return res;
1492     d1 += (len1 + 1);
1493     d2 += (len2 + 1);
1494     length1 -= (len1 + 1);
1495     length2 -= (len2 + 1);
1496
1497     // Compare Replacement
1498     return name_compare(d1, d2, length1, length2);
1499 }
1500
1501 // RFC 1035: MINFO: Two domain names
1502 // RFC 1183: RP: Two domain names
1503 mDNSlocal int dom2_compare(mDNSu8 *d1, mDNSu8 *d2, int length1, int length2)
1504 {
1505     int res, dlen;
1506
1507     // We need at least one byte to start with
1508     if (length1 < 1 || length2 < 1)
1509     {
1510         LogMsg("dom2_compare:1: data too small length1 %d, length2 %d", length1, length2);
1511         return -1;
1512     }
1513     res = name_compare(d1, d2, length1, length2);
1514     if (res != 0) return res;
1515     dlen = DomainNameLength((domainname *)d1);
1516
1517     length1 -= dlen;
1518     length2 -= dlen;
1519     // We need at least one byte to start with
1520     if (length1 < 1 || length2 < 1)
1521     {
1522         LogMsg("dom2_compare:2: data too small length1 %d, length2 %d", length1, length2);
1523         return -1;
1524     }
1525
1526     d1 += dlen;
1527     d2 += dlen;
1528
1529     return name_compare(d1, d2, length1, length2);
1530 }
1531
1532 // MX : preference (2 bytes), domainname
1533 mDNSlocal int mx_compare(rdataComp *const r1, rdataComp *const r2)
1534 {
1535     int res;
1536     int length1, length2;
1537
1538     length1 = r1->rdlength;
1539     length2 = r2->rdlength;
1540
1541     // We need at least two bytes + 1 extra byte for the domainname to start with
1542     if (length1 < 3 || length2 < 3)
1543     {
1544         LogMsg("mx_compare: data too small length1 %d, length2 %d", length1, length2);
1545         return -1;
1546     }
1547
1548     res = DNSMemCmp(r1->rdata, r2->rdata, 2);
1549     if (res != 0) return res;
1550     length1 -= 2;
1551     length2 -= 2;
1552     return name_compare(r1->rdata + 2, r2->rdata + 2, length1, length2);
1553 }
1554
1555 // RFC 2163 (PX) : preference (2 bytes), map822. mapx400 (domainnames)
1556 mDNSlocal int px_compare(rdataComp *const r1, rdataComp *const r2)
1557 {
1558     int res;
1559
1560     // We need at least two bytes + 1 extra byte for the domainname to start with
1561     if (r1->rdlength < 3 || r2->rdlength < 3)
1562     {
1563         LogMsg("px_compare: data too small length1 %d, length2 %d", r1->rdlength, r2->rdlength);
1564         return -1;
1565     }
1566
1567     res = DNSMemCmp(r1->rdata, r2->rdata, 2);
1568     if (res != 0) return res;
1569
1570     return dom2_compare(r1->rdata + 2, r2->rdata + 2, r1->rdlength - 2, r2->rdlength - 2);
1571 }
1572
1573 mDNSlocal int soa_compare(rdataComp *r1, rdataComp *r2)
1574 {
1575     int res, dlen;
1576     int offset1, offset2;
1577     int length1, length2;
1578
1579     length1 = r1->rdlength;
1580     length2 = r2->rdlength;
1581     offset1 = offset2 = 0;
1582
1583     // We need at least 20 bytes plus 1 byte for each domainname
1584     if (length1 < 22 || length2 < 22)
1585     {
1586         LogMsg("soa_compare:1: data too small length1 %d, length2 %d", length1, length2);
1587         return -1;
1588     }
1589
1590     // There are two domainnames followed by 20 bytes of serial, refresh, retry, expire and min
1591     // Compare the names and then the rest of the bytes
1592
1593     res = name_compare(r1->rdata, r2->rdata, length1, length2);
1594     if (res != 0) return res;
1595
1596     dlen = DomainNameLength((domainname *)r1->rdata);
1597
1598     length1 -= dlen;
1599     length2 -= dlen;
1600     if (length1 < 1 || length2 < 1)
1601     {
1602         LogMsg("soa_compare:2: data too small length1 %d, length2 %d", length1, length2);
1603         return -1;
1604     }
1605     offset1 += dlen;
1606     offset2 += dlen;
1607
1608     res = name_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2);
1609     if (res != 0) return res;
1610
1611     dlen = DomainNameLength((domainname *)r1->rdata);
1612     length1 -= dlen;
1613     length2 -= dlen;
1614     if (length1 < 20 || length2 < 20)
1615     {
1616         LogMsg("soa_compare:3: data too small length1 %d, length2 %d", length1, length2);
1617         return -1;
1618     }
1619     offset1 += dlen;
1620     offset2 += dlen;
1621
1622     return (rdata_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2));
1623 }
1624
1625 // RFC 4034 Section 6.0 states that:
1626 //
1627 // A canonical RR form and ordering within an RRset are required in order to
1628 // construct and verify RRSIG RRs.
1629 //
1630 // This function is called to order within an RRset. We can't just do a memcmp as
1631 // as stated in 6.3. This function is responsible for the third bullet in 6.2, where
1632 // the RDATA has to be converted to lower case if it has domain names.
1633 mDNSlocal int RDATACompare(const void *rdata1, const void *rdata2)
1634 {
1635     rdataComp *r1 = (rdataComp *)rdata1;
1636     rdataComp *r2 = (rdataComp *)rdata2;
1637
1638     if (r1->rrtype != r2->rrtype)
1639     {
1640         LogMsg("RDATACompare: ERROR!! comparing rdata of wrong types type1: %d, type2: %d", r1->rrtype, r2->rrtype);
1641         return -1;
1642     }
1643     switch (r1->rrtype)
1644     {
1645     case kDNSType_A:                // 1. Address Record
1646     case kDNSType_NULL:             // 10 NULL RR
1647     case kDNSType_WKS:              // 11 Well-known-service
1648     case kDNSType_HINFO:            // 13 Host information
1649     case kDNSType_TXT:              // 16 Arbitrary text string
1650     case kDNSType_X25:              // 19 X_25 calling address
1651     case kDNSType_ISDN:             // 20 ISDN calling address
1652     case kDNSType_NSAP:             // 22 NSAP address
1653     case kDNSType_KEY:              // 25 Security key
1654     case kDNSType_GPOS:             // 27 Geographical position (withdrawn)
1655     case kDNSType_AAAA:             // 28 IPv6 Address
1656     case kDNSType_LOC:              // 29 Location Information
1657     case kDNSType_EID:              // 31 Endpoint identifier
1658     case kDNSType_NIMLOC:           // 32 Nimrod Locator
1659     case kDNSType_ATMA:             // 34 ATM Address
1660     case kDNSType_CERT:             // 37 Certification record
1661     case kDNSType_A6:               // 38 IPv6 Address (deprecated)
1662     case kDNSType_SINK:             // 40 Kitchen sink (experimental)
1663     case kDNSType_OPT:              // 41 EDNS0 option (meta-RR)
1664     case kDNSType_APL:              // 42 Address Prefix List
1665     case kDNSType_DS:               // 43 Delegation Signer
1666     case kDNSType_SSHFP:            // 44 SSH Key Fingerprint
1667     case kDNSType_IPSECKEY:         // 45 IPSECKEY
1668     case kDNSType_RRSIG:            // 46 RRSIG
1669     case kDNSType_NSEC:             // 47 Denial of Existence
1670     case kDNSType_DNSKEY:           // 48 DNSKEY
1671     case kDNSType_DHCID:            // 49 DHCP Client Identifier
1672     case kDNSType_NSEC3:            // 50 Hashed Authenticated Denial of Existence
1673     case kDNSType_NSEC3PARAM:       // 51 Hashed Authenticated Denial of Existence
1674     case kDNSType_HIP:              // 55 Host Identity Protocol
1675     case kDNSType_SPF:              // 99 Sender Policy Framework for E-Mail
1676     default:
1677         return rdata_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1678     case kDNSType_NS:               //  2 Name Server
1679     case kDNSType_MD:               //  3 Mail Destination
1680     case kDNSType_MF:               //  4 Mail Forwarder
1681     case kDNSType_CNAME:            //  5 Canonical Name
1682     case kDNSType_MB:               //  7 Mailbox
1683     case kDNSType_MG:               //  8 Mail Group
1684     case kDNSType_MR:               //  9 Mail Rename
1685     case kDNSType_PTR:              // 12 Domain name pointer
1686     case kDNSType_NSAP_PTR:         // 23 Reverse NSAP lookup (deprecated)
1687     case kDNSType_DNAME:            // 39 Non-terminal DNAME (for IPv6)
1688         return name_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1689     case kDNSType_SRV:              // 33 Service record
1690         return srv_compare(r1, r2);
1691     case kDNSType_SOA:              //  6 Start of Authority
1692         return soa_compare(r1, r2);
1693
1694     case kDNSType_RP:               // 17 Responsible person
1695     case kDNSType_MINFO:            // 14 Mailbox information
1696         return dom2_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1697     case kDNSType_MX:               // 15 Mail Exchanger
1698     case kDNSType_AFSDB:            // 18 AFS cell database
1699     case kDNSType_RT:               // 21 Router
1700     case kDNSType_KX:               // 36 Key Exchange
1701         return mx_compare(r1, r2);
1702     case kDNSType_PX:               // 26 X.400 mail mapping
1703         return px_compare(r1, r2);
1704     case kDNSType_NAPTR:            // 35 Naming Authority PoinTeR
1705         return naptr_compare(r1, r2);
1706     case kDNSType_TKEY:             // 249 Transaction key
1707     case kDNSType_TSIG:             // 250 Transaction signature
1708         // TSIG and TKEY have a domainname followed by data
1709         return tsig_compare(r1, r2);
1710     // TBD: We are comparing them as opaque types, perhaps not right
1711     case kDNSType_SIG:              // 24 Security signature
1712     case kDNSType_NXT:              // 30 Next domain (security)
1713         LogMsg("RDATACompare: WARNING!! explicit support has not been added, using default");
1714         return rdata_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1715     }
1716 }
1717
1718
1719
1720 // RFC 4034 section 6.2 requirement for verifying signature.
1721 //
1722 // 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1723 // HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
1724 // SRV, DNAME, A6, RRSIG, or NSEC, all uppercase US-ASCII letters in
1725 // the DNS names contained within the RDATA are replaced by the
1726 // corresponding lowercase US-ASCII letters;
1727 //
1728 // NSEC and HINFO is not needed as per dnssec-bis update. RRSIG is done elsewhere
1729 // as part of signature verification
1730 mDNSlocal void ConvertRDATAToCanonical(mDNSu16 rrtype, mDNSu16 rdlength, mDNSu8 *rdata)
1731 {
1732     domainname name;
1733     int len;
1734     mDNSu8 *origRdata = rdata;
1735
1736     // Ensure that we have at least one byte of data to examine and modify.
1737
1738     if (!rdlength) { LogMsg("ConvertRDATAToCanonical: rdlength zero for rrtype %s", DNSTypeName(rrtype)); return; }
1739
1740     switch (rrtype)
1741     {
1742     // Not adding suppot for A6 as it is deprecated
1743     case kDNSType_A6:               // 38 IPv6 Address (deprecated)
1744     default:
1745         debugdnssec("ConvertRDATAToCanonical: returning from default %s", DNSTypeName(rrtype));
1746         return;
1747     case kDNSType_NS:               //  2 Name Server
1748     case kDNSType_MD:               //  3 Mail Destination
1749     case kDNSType_MF:               //  4 Mail Forwarder
1750     case kDNSType_CNAME:            //  5 Canonical Name
1751     case kDNSType_MB:               //  7 Mailbox
1752     case kDNSType_MG:               //  8 Mail Group
1753     case kDNSType_MR:               //  9 Mail Rename
1754     case kDNSType_PTR:              // 12 Domain name pointer
1755     case kDNSType_DNAME:            // 39 Non-terminal DNAME (for IPv6)
1756     case kDNSType_NXT:              // 30 Next domain (security)
1757
1758     // TSIG and TKEY are not mentioned in RFC 4034, but we just leave it here
1759     case kDNSType_TSIG:             // 250 Transaction signature
1760     case kDNSType_TKEY:             // 249 Transaction key
1761
1762         if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1763         {
1764             LogMsg("ConvertRDATAToCanonical: ERROR!! DNSNameToLowerCase failed");
1765             return;
1766         }
1767         AssignDomainName((domainname *)rdata, &name);
1768         return;
1769     case kDNSType_MX:               // 15 Mail Exchanger
1770     case kDNSType_AFSDB:            // 18 AFS cell database
1771     case kDNSType_RT:               // 21 Router
1772     case kDNSType_KX:               // 36 Key Exchange
1773
1774         // format: preference - 2 bytes, followed by name
1775         // Ensure that we have at least 3 bytes (preference + 1 byte for the domain name)
1776         if (rdlength <= 3)
1777         {
1778             LogMsg("ConvertRDATAToCanonical:MX: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1779             return;
1780         }
1781         if (DNSNameToLowerCase((domainname *)(rdata + 2), &name) != mStatus_NoError)
1782         {
1783             LogMsg("ConvertRDATAToCanonical: MX: ERROR!! DNSNameToLowerCase failed");
1784             return;
1785         }
1786         AssignDomainName((domainname *)(rdata + 2), &name);
1787         return;
1788     case kDNSType_SRV:              // 33 Service record
1789         // format : priority, weight and port - 6 bytes, followed by name
1790         if (rdlength <= 7)
1791         {
1792             LogMsg("ConvertRDATAToCanonical:SRV: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1793             return;
1794         }
1795         if (DNSNameToLowerCase((domainname *)(rdata + 6), &name) != mStatus_NoError)
1796         {
1797             LogMsg("ConvertRDATAToCanonical: SRV: ERROR!! DNSNameToLowerCase failed");
1798             return;
1799         }
1800         AssignDomainName((domainname *)(rdata + 6), &name);
1801         return;
1802     case kDNSType_PX:               // 26 X.400 mail mapping
1803         if (rdlength <= 3)
1804         {
1805             LogMsg("ConvertRDATAToCanonical:PX: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1806             return;
1807         }
1808         // Preference followed by two domain names
1809         rdata += 2;
1810     /* FALLTHROUGH */
1811     case kDNSType_RP:               // 17 Responsible person
1812     case kDNSType_SOA:              //  6 Start of Authority
1813     case kDNSType_MINFO:            // 14 Mailbox information
1814         if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1815         {
1816             LogMsg("ConvertRDATAToCanonical: SOA1: ERROR!! DNSNameToLowerCase failed");
1817             return;
1818         }
1819
1820         AssignDomainName((domainname *)rdata, &name);
1821         len = DomainNameLength((domainname *)rdata);
1822         if (rdlength <= len + 1)
1823         {
1824             LogMsg("ConvertRDATAToCanonical:RP: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1825             return;
1826         }
1827         rdata += len;
1828
1829         if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1830         {
1831             LogMsg("ConvertRDATAToCanonical: SOA2: ERROR!! DNSNameToLowerCase failed");
1832             return;
1833         }
1834         AssignDomainName((domainname *)rdata, &name);
1835         return;
1836     case kDNSType_NAPTR:            // 35 Naming Authority Pointer
1837         // order and preference
1838         rdata += 4;
1839         // Flags (including the length byte)
1840         rdata += (((int) rdata[0]) + 1);
1841         // Service (including the length byte)
1842         rdata += (((int) rdata[0]) + 1);
1843         // regexp (including the length byte)
1844         rdata += (((int) rdata[0]) + 1);
1845
1846         // Replacement field is a domainname. If we have at least one more byte, then we are okay.
1847         if ((origRdata + rdlength) < rdata + 1)
1848         {
1849             LogMsg("ConvertRDATAToCanonical:NAPTR: origRdata %p, rdlength %d, rdata %p for rrtype %s too small", origRdata, rdlength, rdata, DNSTypeName(rrtype));
1850             return;
1851         }
1852         if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1853         {
1854             LogMsg("ConvertRDATAToCanonical: NAPTR2: ERROR!! DNSNameToLowerCase failed");
1855             return;
1856         }
1857         AssignDomainName((domainname *)rdata, &name);
1858     case kDNSType_SIG:              // 24 Security signature
1859         // format: <18 bytes> <domainname> <data>
1860         if (rdlength <= 19)
1861         {
1862             LogMsg("ConvertRDATAToCanonical:SIG: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1863             return;
1864         }
1865         // Preference followed by two domain names
1866         rdata += 18;
1867         if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1868         {
1869             LogMsg("ConvertRDATAToCanonical: SIG: ERROR!! DNSNameToLowerCase failed");
1870             return;
1871         }
1872         AssignDomainName((domainname *)rdata, &name);
1873         return;
1874     }
1875 }
1876
1877 mDNSlocal mDNSBool ValidateSignatureWithKey(DNSSECVerifier *dv, RRVerifier *rrset, RRVerifier *keyv, RRVerifier *sig)
1878 {
1879     domainname name;
1880     domainname signerName;
1881     int labels;
1882     mDNSu8 fixedPart[MAX_DOMAIN_NAME + 8];  // domainname + type + class + ttl
1883     int fixedPartLen;
1884     RRVerifier *tmp;
1885     int nrrsets;
1886     rdataComp *ptr, *start, *p;
1887     rdataRRSig *rrsig;
1888     rdataDNSKey *key;
1889     int i;
1890     int sigNameLen;
1891     mDNSu16 temp;
1892     mStatus algRet;
1893
1894
1895     key = (rdataDNSKey *)keyv->rdata;
1896     rrsig = (rdataRRSig *)sig->rdata;
1897
1898     LogDNSSEC("ValidateSignatureWithKey: Validating signature with key with tag %d", (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength));
1899
1900     if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &signerName) != mStatus_NoError)
1901     {
1902         LogMsg("ValidateSignatureWithKey: ERROR!! cannot convert signer name to lower case");
1903         return mDNSfalse;
1904     }
1905
1906     if (DNSNameToLowerCase((domainname *)&rrset->name, &name) != mStatus_NoError)
1907     {
1908         LogMsg("ValidateSignatureWithKey: ERROR!! cannot convert rrset name to lower case");
1909         return mDNSfalse;
1910     }
1911
1912     sigNameLen = DomainNameLength(&signerName);
1913     labels = CountLabels(&name);
1914     // RFC 4034: RRSIG validation
1915     //
1916     // signature = sign(RRSIG_RDATA | RR(1) | RR(2)... )
1917     //
1918     // where RRSIG_RDATA excludes the signature and signer name in canonical form
1919
1920     if (dv->ctx) AlgDestroy(dv->ctx);
1921     dv->ctx = AlgCreate(CRYPTO_ALG, rrsig->alg);
1922     if (!dv->ctx)
1923     {
1924         LogDNSSEC("ValidateSignatureWithKey: ERROR!! No algorithm support for %d", rrsig->alg);
1925         return mDNSfalse;
1926     }
1927     AlgAdd(dv->ctx, (const mDNSu8 *)rrsig, RRSIG_FIXED_SIZE);
1928     AlgAdd(dv->ctx, signerName.c, sigNameLen);
1929
1930     if (labels - rrsig->labels > 0)
1931     {
1932         domainname *d;
1933         LogDNSSEC("ValidateSignatureWithKey: ====splitting labels %d, rrsig->labels %d====", labels,rrsig->labels);
1934         d = (domainname *)SkipLeadingLabels(&name, labels - rrsig->labels);
1935         fixedPart[0] = 1;
1936         fixedPart[1] = '*';
1937         AssignDomainName((domainname *)(fixedPart + 2), d);
1938         fixedPartLen = DomainNameLength(d) + 2;
1939         // See RFC 4034 section 3.1.3. If you are looking up *.example.com,
1940         // the labels count in the RRSIG is 2, but this is not considered as
1941         // a wildcard answer
1942         if (name.c[0] != 1 || name.c[1] != '*')
1943         {
1944             LogDNSSEC("ValidateSignatureWithKey: Wildcard exapnded answer for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
1945             dv->flags |= WILDCARD_PROVES_ANSWER_EXPANDED;
1946             dv->wildcardName = (domainname *)SkipLeadingLabels(&dv->origName, labels - rrsig->labels);
1947             if (!dv->wildcardName) return mDNSfalse;
1948         }
1949     }
1950     else
1951     {
1952         debugdnssec("ValidateSignatureWithKey: assigning domainname");
1953         AssignDomainName((domainname *)fixedPart, &name);
1954         fixedPartLen = DomainNameLength(&name);
1955     }
1956     temp = swap16(rrset->rrtype);
1957     mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&temp, sizeof(rrset->rrtype));
1958     fixedPartLen += sizeof(rrset->rrtype);
1959     temp = swap16(rrset->rrclass);
1960     mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&temp, sizeof(rrset->rrclass));
1961     fixedPartLen += sizeof(rrset->rrclass);
1962     mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&rrsig->origTTL, sizeof(rrsig->origTTL));
1963     fixedPartLen += sizeof(rrsig->origTTL);
1964
1965
1966     for (tmp = rrset, nrrsets = 0; tmp; tmp = tmp->next)
1967         nrrsets++;
1968
1969     tmp = rrset;
1970     start = ptr = mDNSPlatformMemAllocate(nrrsets * sizeof (rdataComp));
1971     debugdnssec("ValidateSignatureWithKey: start %p, nrrsets %d", start, nrrsets);
1972     if (ptr)
1973     {
1974         // Need to initialize for failure case below
1975         mDNSPlatformMemZero(ptr, nrrsets * (sizeof (rdataComp)));
1976         while (tmp)
1977         {
1978             ptr->rdlength = tmp->rdlength;
1979             ptr->rrtype = tmp->rrtype;
1980             if (ptr->rdlength)
1981             {
1982                 ptr->rdata = mDNSPlatformMemAllocate(ptr->rdlength);
1983                 if (ptr->rdata)
1984                 {
1985                     mDNSPlatformMemCopy(ptr->rdata, tmp->rdata, tmp->rdlength);
1986                 }
1987                 else
1988                 {
1989                     for (i = 0; i < nrrsets; i++)
1990                         if (start[i].rdata) mDNSPlatformMemFree(start[i].rdata);
1991                     mDNSPlatformMemFree(start);
1992                     LogMsg("ValidateSignatureWithKey:1: ERROR!! RDATA memory alloation failure");
1993                     return mDNSfalse;
1994                 }
1995             }
1996             ptr++;
1997             tmp = tmp->next;
1998         }
1999     }
2000     else
2001     {
2002         LogMsg("ValidateSignatureWithKey:2: ERROR!! RDATA memory alloation failure");
2003         return mDNSfalse;
2004     }
2005
2006     PrintFixedSignInfo(rrsig, &signerName, sigNameLen, fixedPart, fixedPartLen);
2007
2008     mDNSPlatformQsort(start, nrrsets, sizeof(rdataComp), RDATACompare);
2009     for (p = start, i = 0; i < nrrsets; p++, i++)
2010     {
2011         int rdlen;
2012
2013         // The array is sorted and hence checking adjacent entries for duplicate is sufficient
2014         if (i > 0)
2015         {
2016             rdataComp *q = p - 1;
2017             if (!RDATACompare((void *)p, (void *)q)) continue;
2018         }
2019
2020         // Add the fixed part
2021         AlgAdd(dv->ctx, (const mDNSu8 *)fixedPart, fixedPartLen);
2022
2023         // Add the rdlength
2024         rdlen = swap16(p->rdlength);
2025         AlgAdd(dv->ctx, (const mDNSu8 *)&rdlen, sizeof(mDNSu16));
2026
2027         ConvertRDATAToCanonical(p->rrtype, p->rdlength, p->rdata);
2028
2029         PrintVarSignInfo(rdlen, p->rdata);
2030         AlgAdd(dv->ctx, (const mDNSu8 *)p->rdata, p->rdlength);
2031     }
2032     // free the memory as we don't need it anymore
2033     for (i = 0; i < nrrsets; i++)
2034         if (start[i].rdata) mDNSPlatformMemFree(start[i].rdata);
2035     mDNSPlatformMemFree(start);
2036
2037     algRet = AlgVerify(dv->ctx, (mDNSu8 *)&key->data, keyv->rdlength - DNSKEY_FIXED_SIZE, (mDNSu8 *)(sig->rdata + sigNameLen + RRSIG_FIXED_SIZE), sig->rdlength - RRSIG_FIXED_SIZE - sigNameLen);
2038     AlgDestroy(dv->ctx);
2039     dv->ctx = mDNSNULL;
2040     if (algRet != mStatus_NoError)
2041     {
2042         LogDNSSEC("ValidateSignatureWithKey: AlgVerify failed for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2043         // Reset the state if we set any above.
2044         if (dv->flags & WILDCARD_PROVES_ANSWER_EXPANDED)
2045         {
2046             dv->flags &= ~WILDCARD_PROVES_ANSWER_EXPANDED;
2047             dv->wildcardName = mDNSNULL;
2048         }
2049         return mDNSfalse;
2050     }
2051     return mDNStrue;
2052 }
2053
2054 // Walk all the keys and for each key walk all the RRSIGS that signs the original rrset
2055 mDNSlocal mStatus ValidateSignature(DNSSECVerifier *dv, RRVerifier **resultKey, RRVerifier **resultRRSIG)
2056 {
2057     RRVerifier *rrset;
2058     RRVerifier *keyv;
2059     RRVerifier *rrsigv;
2060     RRVerifier *sig;
2061     rdataDNSKey *key;
2062     rdataRRSig *rrsig;
2063     mDNSu16 tag;
2064
2065     rrset = dv->rrset;
2066     sig = dv->rrsig;
2067
2068     for (keyv = dv->key; keyv; keyv = keyv->next)
2069     {
2070         key = (rdataDNSKey *)keyv->rdata;
2071         tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
2072         for (rrsigv = sig; rrsigv; rrsigv = rrsigv->next)
2073         {
2074             rrsig = (rdataRRSig *)rrsigv->rdata;
2075             // 7. The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST match the owner
2076             //    name, algorithm, and key tag for some DNSKEY RR in the zone's apex DNSKEY RRset.
2077             if (!SameDomainName((domainname *)&rrsig->signerName, &keyv->name))
2078             {
2079                 debugdnssec("ValidateSignature: name mismatch");
2080                 continue;
2081             }
2082             if (key->alg != rrsig->alg)
2083             {
2084                 debugdnssec("ValidateSignature: alg mismatch");
2085                 continue;
2086             }
2087             if (tag != swap16(rrsig->keyTag))
2088             {
2089                 debugdnssec("ValidateSignature: keyTag mismatch rrsig tag %d(0x%x), keyTag %d(0x%x)", swap16(rrsig->keyTag),
2090                             swap16(rrsig->keyTag), tag, tag);
2091                 continue;
2092             }
2093             // 8. The matching DNSKEY RR MUST be present in the zone's apex DNSKEY RRset, and MUST
2094             //    have the Zone Flag bit (DNSKEY RDATA Flag bit 7) set.
2095             if (!((swap16(key->flags)) & DNSKEY_ZONE_SIGN_KEY))
2096             {
2097                 debugdnssec("ValidateSignature: ZONE flag bit not set");
2098                 continue;
2099             }
2100             debugdnssec("ValidateSignature:Found a key and RRSIG tag: %d", tag);
2101             if (ValidateSignatureWithKey(dv, rrset, keyv, rrsigv))
2102             {
2103                 LogDNSSEC("ValidateSignature: Validated successfully with key tag %d", tag);
2104                 *resultKey = keyv;
2105                 *resultRRSIG = rrsigv;
2106                 return mStatus_NoError;
2107             }
2108         }
2109     }
2110     *resultKey = mDNSNULL;
2111     *resultRRSIG = mDNSNULL;
2112     return mStatus_NoSuchRecord;
2113 }
2114
2115 mDNSlocal mDNSBool ValidateSignatureWithKeyForAllRRSigs(DNSSECVerifier *dv, RRVerifier *rrset, RRVerifier *keyv, RRVerifier *sig)
2116 {
2117     rdataRRSig *rrsig;
2118     mDNSu16 tag;
2119
2120     while (sig)
2121     {
2122         rrsig = (rdataRRSig *)sig->rdata;
2123         tag = (mDNSu16)keytag(keyv->rdata, keyv->rdlength);
2124         if (tag == swap16(rrsig->keyTag))
2125         {
2126             if (ValidateSignatureWithKey(dv, rrset, keyv, sig))
2127             {
2128                 LogDNSSEC("ValidateSignatureWithKeyForAllRRSigs: Validated");
2129                 return mDNStrue;
2130             }
2131         }
2132         sig = sig->next;
2133     }
2134     return mDNSfalse;
2135 }
2136
2137 mDNSlocal mStatus ValidateDS(DNSSECVerifier *dv)
2138 {
2139     mDNSu8 *digest;
2140     int digestLen;
2141     domainname name;
2142     rdataRRSig *rrsig;
2143     rdataDS *ds;
2144     rdataDNSKey *key;
2145     RRVerifier *keyv;
2146     RRVerifier *dsv;
2147     mStatus algRet;
2148
2149     rrsig = (rdataRRSig *)dv->rrsig->rdata;
2150
2151     // Walk all the DS Records to see if we have a matching DNS KEY record that verifies
2152     // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
2153     // this zone. Loop till we find one.
2154     for (dsv = dv->ds; dsv; dsv = dsv->next)
2155     {
2156         ds = (rdataDS *)dsv->rdata;
2157         if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
2158         {
2159             LogDNSSEC("ValidateDS: Unsupported digest %d", ds->digestType);
2160             return mStatus_BadParamErr;
2161         }
2162         else debugdnssec("ValidateDS: digest type %d", ds->digestType);
2163         for (keyv = dv->key; keyv; keyv = keyv->next)
2164         {
2165             key = (rdataDNSKey *)keyv->rdata;
2166             mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
2167             if (tag != swap16(ds->keyTag))
2168             {
2169                 debugdnssec("ValidateDS:Not a valid keytag %d", tag);
2170                 continue;
2171             }
2172
2173             if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &name) != mStatus_NoError)
2174             {
2175                 LogMsg("ValidateDS: ERROR!! cannot convert to lower case");
2176                 continue;
2177             }
2178
2179             if (dv->ctx) AlgDestroy(dv->ctx);
2180             dv->ctx = AlgCreate(DIGEST_ALG, ds->digestType);
2181             if (!dv->ctx)
2182             {
2183                 LogMsg("ValidateDS: ERROR!! Cannot allocate context");
2184                 continue;
2185             }
2186             digest = (mDNSu8 *)&ds->digest;
2187             digestLen = dsv->rdlength - DS_FIXED_SIZE;
2188
2189             AlgAdd(dv->ctx, name.c, DomainNameLength(&name));
2190             AlgAdd(dv->ctx, (const mDNSu8 *)key, keyv->rdlength);
2191
2192             algRet = AlgVerify(dv->ctx, mDNSNULL, 0, digest, digestLen);
2193             AlgDestroy(dv->ctx);
2194             dv->ctx = mDNSNULL;
2195             if (algRet == mStatus_NoError)
2196             {
2197                 LogDNSSEC("ValidateDS: DS Validated Successfully, need to verify the key %d", tag);
2198                 // We found the DNS KEY that is authenticated by the DS in our parent zone. Check to see if this key
2199                 // was used to sign the DNS KEY RRSET. If so, then the keys in our DNS KEY RRSET are valid
2200                 if (ValidateSignatureWithKeyForAllRRSigs(dv, dv->key, keyv, dv->rrsigKey))
2201                 {
2202                     LogDNSSEC("ValidateDS: DS Validated Successfully %d", tag);
2203                     return mStatus_NoError;
2204                 }
2205             }
2206         }
2207     }
2208     return mStatus_NoSuchRecord;
2209 }
2210
2211 mDNSlocal mDNSBool UnlinkRRVerifier(DNSSECVerifier *dv, RRVerifier *elem, RRVerifierSet set)
2212 {
2213     RRVerifier **v;
2214
2215     switch (set)
2216     {
2217     case RRVS_rr:
2218         v = &dv->rrset;
2219         break;
2220     case RRVS_rrsig:
2221         v = &dv->rrsig;
2222         break;
2223     case RRVS_key:
2224         v = &dv->key;
2225         break;
2226     case RRVS_rrsig_key:
2227         v = &dv->rrsigKey;
2228         break;
2229     case RRVS_ds:
2230         v = &dv->ds;
2231         break;
2232     default:
2233         LogMsg("UnlinkRRVerifier: ERROR!! default case %d", set);
2234         return mDNSfalse;
2235     }
2236     while (*v && *v != elem)
2237         v = &(*v)->next;
2238     if (!(*v))
2239     {
2240         LogMsg("UnlinkRRVerifier: ERROR!! cannot find element in set %d", set);
2241         return mDNSfalse;
2242     }
2243     *v = elem->next;                  // Cut this record from the list
2244     elem->next = mDNSNULL;
2245     return mDNStrue;
2246 }
2247
2248 // This can link a single AuthChain element or a list of AuthChain elements to
2249 // DNSSECVerifier. The latter happens when we have multiple NSEC proofs and
2250 // we gather up all the proofs in one place.
2251 mDNSexport void AuthChainLink(DNSSECVerifier *dv, AuthChain *ae)
2252 {
2253     AuthChain *head;
2254
2255     LogDNSSEC("AuthChainLink: called");
2256
2257     head = ae;
2258     // Get to the last element
2259     while (ae->next)
2260         ae = ae->next;
2261     *(dv->actail) = head;                // Append this record to tail of auth chain
2262     dv->actail = &(ae->next);          // Advance tail pointer
2263 }
2264
2265 mDNSlocal mDNSBool AuthChainAdd(DNSSECVerifier *dv, RRVerifier *resultKey, RRVerifier *resultRRSig)
2266 {
2267     AuthChain *ae;
2268     rdataDNSKey *key;
2269     mDNSu16 tag;
2270
2271     if (!dv->rrset || !resultKey || !resultRRSig)
2272     {
2273         LogMsg("AuthChainAdd: ERROR!! input argument NULL");
2274         return mDNSfalse;
2275     }
2276
2277     // Unlink resultKey and resultRRSig and store as part of AuthChain
2278     if (!UnlinkRRVerifier(dv, resultKey, RRVS_key))
2279     {
2280         LogMsg("AuthChainAdd: ERROR!! cannot unlink key");
2281         return mDNSfalse;
2282     }
2283     if (!UnlinkRRVerifier(dv, resultRRSig, RRVS_rrsig))
2284     {
2285         LogMsg("AuthChainAdd: ERROR!! cannot unlink rrsig");
2286         return mDNSfalse;
2287     }
2288
2289     ae = mDNSPlatformMemAllocate(sizeof(AuthChain));
2290     if (!ae)
2291     {
2292         LogMsg("AuthChainAdd: AuthChain alloc failure");
2293         return mDNSfalse;
2294     }
2295
2296     ae->next  = mDNSNULL;
2297     ae->rrset = dv->rrset;
2298     dv->rrset = mDNSNULL;
2299
2300     ae->rrsig = resultRRSig;
2301     ae->key   = resultKey;
2302
2303     key = (rdataDNSKey *)resultKey->rdata;
2304     tag = (mDNSu16)keytag((mDNSu8 *)key, resultKey->rdlength);
2305     LogDNSSEC("AuthChainAdd: inserting AuthChain element with rrset %##s (%s), DNSKEY tag %d", ae->rrset->name.c, DNSTypeName(ae->rrset->rrtype), tag);
2306
2307     AuthChainLink(dv, ae);
2308     return mDNStrue;
2309 }
2310         
2311 // RFC 4035: Section 5.3.3
2312 //
2313 // If the resolver accepts the RRset as authentic, the validator MUST set the TTL of
2314 // the RRSIG RR and each RR in the authenticated RRset to a value no greater than the
2315 // minimum of:
2316 //
2317 //   o  the RRset's TTL as received in the response;
2318 //
2319 //   o  the RRSIG RR's TTL as received in the response;
2320 //
2321 //   o  the value in the RRSIG RR's Original TTL field; and
2322 //
2323 //   o  the difference of the RRSIG RR's Signature Expiration time and the
2324 //      current time.
2325 mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
2326 {
2327     DNSQuestion question;
2328     CacheRecord *rr;
2329     RRVerifier *rrsigv;
2330     rdataRRSig *rrsig;
2331     CacheGroup *cg;
2332     mDNSu32 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL;
2333     domainname *qname;
2334     mDNSu16 qtype;
2335     CacheRecord *rrsigRR;
2336     mDNSs32 now;
2337
2338     debugdnssec("SetTTLRRSet called");
2339
2340     if (status == DNSSEC_Insecure || status == DNSSEC_Indeterminate)
2341     {
2342         LogDNSSEC("SetTTLRRSET: not setting ttl for status %s", DNSSECStatusName(status));
2343         return;
2344     }
2345
2346     mDNS_Lock(m);
2347     now = m->timenow;
2348     mDNS_Unlock(m);
2349
2350     mDNSPlatformMemZero(&question, sizeof(DNSQuestion));
2351     rrTTL = rrsigTTL = rrsigOrigTTL = rrsigTimeTTL = 0;
2352
2353     // 1. Locate the rrset name and get its TTL (take the first one as a representative
2354     // of the rrset). Ideally, we should set the TTL on the first validation. Instead,
2355     // we do it whenever we validate which happens whenever a ValidationRequired question
2356     // finishes validation. 
2357     qname = &dv->origName;
2358     qtype = dv->origType;
2359
2360     question.ThisQInterval = -1;
2361     InitializeQuestion(m, &question, dv->InterfaceID, qname, qtype, mDNSNULL, mDNSNULL);
2362     cg = CacheGroupForName(m, question.qnamehash, &question.qname);
2363
2364     if (!cg)
2365     {
2366         LogMsg("SetTTLRRSet cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2367         return;
2368     }
2369
2370     for (rr = cg->members; rr; rr = rr->next)
2371         if (SameNameRecordAnswersQuestion(&rr->resrec, &question))
2372         {
2373             // originalttl is never touched. The actual TTL is derived based on when it was
2374             // received.
2375             rrTTL = rr->resrec.rroriginalttl - (now - rr->TimeRcvd)/mDNSPlatformOneSecond;
2376             break;
2377         }
2378
2379     // Should we check to see if it matches the record in dv->ac->rrset ?
2380     if (!rr)
2381     {
2382         LogMsg("SetTTLRRSet: ERROR!! cannot locate main rrset for %##s (%s)", qname->c, DNSTypeName(qtype));
2383         return;
2384     }
2385
2386
2387     // 2. Get the RRSIG ttl. For NSEC records we need to get the NSEC record's TTL as
2388     // the negative cache record that we created may not be right.
2389
2390     if (dv->ac && dv->ac->rrsig)
2391     {
2392         rrsigv = dv->ac->rrsig;
2393         rrsig = (rdataRRSig *)rrsigv->rdata;
2394     }
2395     else
2396     {
2397         rrsigv = mDNSNULL;
2398         rrsig = mDNSNULL;
2399     }
2400
2401     rrsigRR = mDNSNULL;
2402     if (rr->resrec.RecordType == kDNSRecordTypePacketNegative && status == DNSSEC_Secure)
2403     {
2404         CacheRecord *ncr;
2405         rrTTL = 0;
2406         for (ncr = rr->nsec; ncr; ncr = ncr->next)
2407         {
2408             if (ncr->resrec.rrtype == kDNSType_NSEC || ncr->resrec.rrtype == kDNSType_NSEC3)
2409             {
2410                 rrTTL = ncr->resrec.rroriginalttl - (now - ncr->TimeRcvd)/mDNSPlatformOneSecond;
2411                 debugdnssec("SetTTLRRSet: NSEC TTL %u", rrTTL);
2412             }
2413             // Note: we can't use dv->origName here as the NSEC record's RRSIG may not match
2414             // the original name
2415             if (rrsigv && ncr->resrec.rrtype == kDNSType_RRSIG && SameDomainName(ncr->resrec.name, &rrsigv->name))
2416             {
2417                 RDataBody2 *rdb = (RDataBody2 *)ncr->resrec.rdata->u.data;
2418                 rdataRRSig *sig = (rdataRRSig *)rdb->data;
2419                 if (rrsigv->rdlength != ncr->resrec.rdlength)
2420                 {
2421                     debugdnssec("SetTTLRRSet length mismatch");
2422                     continue;
2423                 }
2424                 if (mDNSPlatformMemSame(sig, rrsig, rrsigv->rdlength))
2425                 {
2426                     mDNSu32 remain = (now - ncr->TimeRcvd)/mDNSPlatformOneSecond;
2427                     rrsigTTL = ncr->resrec.rroriginalttl - remain;
2428                     rrsigOrigTTL = swap32(rrsig->origTTL) - remain;
2429                     rrsigTimeTTL = swap32(rrsig->sigExpireTime) - swap32(rrsig->sigInceptTime);
2430                 }
2431             }
2432             if (rrTTL && (!rrsigv || rrsigTTL)) break;
2433         }
2434     }
2435     else if (rrsigv)
2436     {
2437         // Look for the matching RRSIG so that we can get its TTL
2438         for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2439             if (rr->resrec.rrtype == kDNSType_RRSIG && SameDomainName(rr->resrec.name, &rrsigv->name))
2440             {
2441                 RDataBody2 *rdb = (RDataBody2 *)rr->resrec.rdata->u.data;
2442                 rdataRRSig *sig = (rdataRRSig *)rdb->data;
2443                 if (rrsigv->rdlength != rr->resrec.rdlength)
2444                 {
2445                     debugdnssec("SetTTLRRSet length mismatch");
2446                     continue;
2447                 }
2448                 if (mDNSPlatformMemSame(sig, rrsig, rrsigv->rdlength))
2449                 {
2450                     mDNSu32 remain = (now - rr->TimeRcvd)/mDNSPlatformOneSecond;
2451                     rrsigTTL = rr->resrec.rroriginalttl - remain;
2452                     rrsigOrigTTL = swap32(rrsig->origTTL) - remain;
2453                     rrsigTimeTTL = swap32(rrsig->sigExpireTime) - swap32(rrsig->sigInceptTime);
2454                     rrsigRR = rr;
2455                     break;
2456                 }
2457             }
2458     }
2459
2460     // It is possible that there are no RRSIGs and in that case it is not an error
2461     // to find the rrsigTTL.
2462     if (!rrTTL || (rrsigv && (!rrsigTTL || !rrsigOrigTTL || !rrsigTimeTTL)))
2463     {
2464         LogDNSSEC("SetTTLRRSet: ERROR!! Bad TTL rrtl %u, rrsigTTL %u, rrsigOrigTTL %u, rrsigTimeTTL %u for %##s (%s)",
2465                rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL, qname->c, DNSTypeName(qtype));
2466         return;
2467     }
2468     LogDNSSEC("SetTTLRRSet: TTL rrtl %u, rrsigTTL %u, rrsigOrigTTL %u, rrsigTimeTTL %u for %##s (%s)",
2469         rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL, qname->c, DNSTypeName(qtype));
2470
2471     if (status == DNSSEC_Bogus)
2472     {
2473         rrTTL = RR_BOGUS_TTL;
2474         LogDNSSEC("SetTTLRRSet: setting to bogus TTL %d", rrTTL);
2475     }
2476
2477     if (rrsigv)
2478     {
2479         if (rrsigTTL < rrTTL)
2480             rrTTL = rrsigTTL;
2481         if (rrsigOrigTTL < rrTTL)
2482             rrTTL = rrsigOrigTTL;
2483         if (rrsigTimeTTL < rrTTL)
2484             rrTTL = rrsigTimeTTL;
2485     }
2486
2487     // Set the rrsig's TTL. For NSEC records, rrsigRR is NULL which means it expires when
2488     // the negative cache record expires.
2489     if (rrsigRR)
2490     {
2491         rrsigRR->resrec.rroriginalttl = rrTTL;
2492         rrsigRR->TimeRcvd = now;
2493         rrsigRR->UnansweredQueries = 0;
2494     }
2495
2496     // Find the RRset and set its TTL
2497     for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2498     {
2499         if (SameNameRecordAnswersQuestion(&rr->resrec, &question))
2500         {
2501             LogDNSSEC("SetTTLRRSet: Setting the TTL %d for %s, question %##s (%s)", rrTTL, CRDisplayString(m, rr),
2502                       question.qname.c, DNSTypeName(rr->resrec.rrtype));
2503             rr->resrec.rroriginalttl = rrTTL;
2504             rr->TimeRcvd = now;
2505             rr->UnansweredQueries = 0;
2506             SetNextCacheCheckTimeForRecord(m, rr);
2507         }
2508     }
2509 }
2510
2511 mDNSlocal void FinishDNSSECVerification(mDNS *const m, DNSSECVerifier *dv)
2512 {
2513     RRVerifier *resultKey;
2514     RRVerifier *resultRRSig;
2515
2516     LogDNSSEC("FinishDNSSECVerification: all rdata sets available for sig verification for %##s (%s)",
2517               dv->origName.c, DNSTypeName(dv->origType));
2518
2519     // Stop outstanding query if one exists
2520     if (dv->q.ThisQInterval != -1)
2521         mDNS_StopQuery(m, &dv->q);
2522     if (ValidateSignature(dv, &resultKey, &resultRRSig) == mStatus_NoError)
2523     {
2524         rdataDNSKey *key;
2525         mDNSu16 tag;
2526         key = (rdataDNSKey *)resultKey->rdata;
2527         tag = (mDNSu16)keytag((mDNSu8 *)key, resultKey->rdlength);
2528
2529         LogDNSSEC("FinishDNSSECVerification: RRSIG validated by DNSKEY tag %d, %##s (%s)", tag, dv->rrset->name.c,
2530                   DNSTypeName(dv->rrset->rrtype));
2531
2532         if (TrustedKey(m, dv) == mStatus_NoError)
2533         {
2534             // Need to call this after we called TrustedKey, as AuthChainAdd
2535             // unlinks the resultKey and resultRRSig
2536             if (!AuthChainAdd(dv, resultKey, resultRRSig))
2537             {
2538                 dv->DVCallback(m, dv, DNSSEC_Bogus);
2539                 return;
2540             }
2541             // The callback will be called when NSEC verification is done.
2542             if ((dv->flags & WILDCARD_PROVES_ANSWER_EXPANDED))
2543             {
2544                 WildcardAnswerProof(m, dv);
2545                 return;
2546             }
2547             else
2548             {
2549                 dv->DVCallback(m, dv, DNSSEC_Secure);
2550                 return;
2551             }
2552         }
2553         if (!ValidateDS(dv))
2554         {
2555             // Need to call this after we called ValidateDS, as AuthChainAdd
2556             // unlinks the resultKey and resultRRSig
2557             if (!AuthChainAdd(dv, resultKey, resultRRSig))
2558             {
2559                 dv->DVCallback(m, dv, DNSSEC_Bogus);
2560                 return;
2561             }
2562             FreeDNSSECVerifierRRSets(dv);
2563             dv->recursed++;
2564             if (dv->recursed < MAX_RECURSE_COUNT)
2565             {
2566                 LogDNSSEC("FinishDNSSECVerification: Recursion level %d for %##s (%s)", dv->recursed, dv->origName.c,
2567                           DNSTypeName(dv->origType));
2568                 VerifySignature(m, dv, &dv->q);
2569                 return;
2570             }
2571         }
2572         else
2573         {
2574             LogDNSSEC("FinishDNSSECVerification: ValidateDS failed %##s (%s)", dv->rrset->name.c, DNSTypeName(dv->rrset->rrtype));
2575             dv->DVCallback(m, dv, DNSSEC_Bogus);
2576             return;
2577         }
2578     }
2579     else
2580     {
2581         LogDNSSEC("FinishDNSSECVerification: Could not validate the rrset %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2582         dv->DVCallback(m, dv, DNSSEC_Bogus);
2583         return;
2584     }
2585 }
2586
2587 mDNSexport void StartDNSSECVerification(mDNS *const m, void *context)
2588 {
2589     mDNSBool done;
2590     DNSSECVerifier *dv = (DNSSECVerifier *)context;
2591
2592     done = GetAllRRSetsForVerification(m, dv);
2593     if (done)
2594     {
2595         if (dv->next != RRVS_done)
2596             LogMsg("StartDNSSECVerification: ERROR!! dv->next is not done");
2597         else
2598             LogDNSSEC("StartDNSSECVerification: all rdata sets available for sig verification");
2599         FinishDNSSECVerification(m, dv);
2600         return;
2601     }
2602     else debugdnssec("StartDNSSECVerification: all rdata sets not available for sig verification next %d", dv->next);
2603 }
2604
2605 mDNSexport char *DNSSECStatusName(DNSSECStatus status)
2606 {
2607     switch (status)
2608     {
2609     case DNSSEC_Secure: return "Secure";
2610     case DNSSEC_Insecure: return "Insecure";
2611     case DNSSEC_Indeterminate: return "Indeterminate";
2612     case DNSSEC_Bogus: return "Bogus";
2613     default: return "Invalid";
2614     }
2615 }
2616
2617 // We could not use GenerateNegativeResponse as it assumes m->CurrentQuestion to be set. Even if
2618 // we change that, we needs to fix its callers and so on. It is much simpler to call the callback.
2619 mDNSlocal void DeliverDNSSECStatus(mDNS *const m, DNSSECVerifier *dv, ResourceRecord *answer, DNSSECStatus status)
2620 {
2621
2622     // Can't use m->CurrentQuestion as it may already be in use
2623     if (m->ValidationQuestion)
2624         LogMsg("DeliverDNSSECStatus: ERROR!! m->ValidationQuestion already set: %##s (%s)",
2625                m->ValidationQuestion->qname.c, DNSTypeName(m->ValidationQuestion->qtype));
2626
2627     BumpDNSSECStats(m, kStatsActionSet, kStatsTypeStatus, status);
2628     BumpDNSSECStats(m, kStatsActionSet, kStatsTypeExtraPackets, dv->NumPackets);
2629     mDNS_Lock(m);
2630     BumpDNSSECStats(m, kStatsActionSet, kStatsTypeLatency, m->timenow - dv->StartTime);
2631     mDNS_Unlock(m);
2632
2633     m->ValidationQuestion = m->Questions;
2634     while (m->ValidationQuestion && m->ValidationQuestion != m->NewQuestions)
2635     {
2636         DNSQuestion *q = m->ValidationQuestion;
2637
2638         if (q->ValidatingResponse || !q->ValidationRequired ||
2639            (q->ValidationState != DNSSECValInProgress) || !ResourceRecordAnswersQuestion(answer, q))
2640         {
2641             m->ValidationQuestion = q->next;
2642             continue;
2643         }
2644
2645         q->ValidationState = DNSSECValDone;
2646         q->ValidationStatus = status;
2647
2648         MakeNegativeCacheRecord(m, &largerec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL);
2649         if (q->qtype == answer->rrtype || status != DNSSEC_Secure)
2650         {
2651             LogDNSSEC("DeliverDNSSECStatus: Generating dnssec status %s for %##s (%s)", DNSSECStatusName(status),
2652                 q->qname.c, DNSTypeName(q->qtype));
2653             if (q->QuestionCallback)
2654             {
2655                 if (q->DNSSECAuthInfo)
2656                     FreeDNSSECAuthChainInfo((AuthChain *)q->DNSSECAuthInfo);
2657                 q->DNSSECAuthInfo = AuthChainCopy(dv->ac);
2658                 q->DAIFreeCallback = FreeAuthChain;
2659                 q->QuestionCallback(m, q, &largerec.r.resrec, QC_dnssec);
2660             }
2661         }
2662         else if (FollowCNAME(q, answer, QC_add))
2663         {
2664             LogDNSSEC("DeliverDNSSECStatus: Following CNAME dnssec status %s for %##s (%s)", DNSSECStatusName(status),
2665                 q->qname.c, DNSTypeName(q->qtype));
2666             mDNS_Lock(m); 
2667             AnswerQuestionByFollowingCNAME(m, q, answer);
2668             mDNS_Unlock(m);
2669         }
2670
2671         if (m->ValidationQuestion == q)    // If m->ValidationQuestion was not auto-advanced, do it ourselves now
2672             m->ValidationQuestion = q->next;
2673     }
2674     m->ValidationQuestion = mDNSNULL;
2675 }
2676
2677 // There is no work to be done if we could not validate DNSSEC (as the actual response for
2678 // the query has already been delivered) except in the case of CNAMEs where we did not follow
2679 // CNAMEs until we finished the DNSSEC processing.
2680 mDNSlocal void DNSSECNoResponse(mDNS *const m, DNSSECVerifier *dv)
2681 {
2682     CacheGroup *cg;
2683     CacheRecord *cr;
2684     mDNSu32 namehash;
2685     ResourceRecord *answer = mDNSNULL;
2686
2687     LogDNSSEC("DNSSECNoResponse: called");
2688
2689     if (dv->ValidationRequired != DNSSEC_VALIDATION_SECURE_OPTIONAL)
2690     {
2691         LogMsg("DNSSECNoResponse: ERROR!! ValidationRequired incorrect %d", dv->ValidationRequired);
2692         return;
2693     }
2694
2695     BumpDNSSECStats(m, kStatsActionSet, kStatsTypeStatus, DNSSEC_NoResponse);
2696
2697     namehash = DomainNameHashValue(&dv->origName);
2698
2699     cg = CacheGroupForName(m, namehash, &dv->origName);
2700     if (!cg)
2701     {
2702         LogDNSSEC("DNSSECNoResponse: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2703         goto done;
2704     }
2705
2706     InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->origName, dv->origType, mDNSNULL, mDNSNULL);
2707
2708     // We don't have to reset ValidatingResponse (unlike in DeliverDNSSECStatus) as there are no
2709     // RRSIGs that can match the original question
2710     for (cr = cg->members; cr; cr = cr->next)
2711     {
2712         if (SameNameRecordAnswersQuestion(&cr->resrec, &dv->q))
2713         {
2714             answer = &cr->resrec;
2715             break;
2716         }
2717     }
2718
2719     // It is not an error for things to disappear underneath
2720     if (!answer)
2721     {
2722         LogDNSSEC("DNSSECNoResponse: answer NULL for %##s, %s", dv->origName.c, DNSTypeName(dv->origType));
2723         goto done;
2724     }
2725     if (answer->rrtype == kDNSType_RRSIG)
2726     {
2727         LogDNSSEC("DNSSECNoResponse: RRSIG present for %##s, %s", dv->origName.c, DNSTypeName(dv->origType));
2728         goto done;
2729     }
2730
2731     // Can't use m->CurrentQuestion as it may already be in use
2732     if (m->ValidationQuestion)
2733         LogMsg("DNSSECNoResponse: ERROR!! m->ValidationQuestion already set: %##s (%s)",
2734                m->ValidationQuestion->qname.c, DNSTypeName(m->ValidationQuestion->qtype));
2735
2736     m->ValidationQuestion = m->Questions;
2737     while (m->ValidationQuestion && m->ValidationQuestion != m->NewQuestions)
2738     {
2739         DNSQuestion *q = m->ValidationQuestion;
2740
2741         if (q->ValidatingResponse || !q->ValidationRequired ||
2742            (q->ValidationState != DNSSECValInProgress) || !ResourceRecordAnswersQuestion(answer, q))
2743         {
2744             m->ValidationQuestion = q->next;
2745             continue;
2746         }
2747
2748         // If we could not validate e.g., zone was not signed or bad delegation etc., 
2749         // disable validation. Ideally, for long outstanding questions, we should try again when
2750         // we switch networks. But for now, keep it simple.
2751         // 
2752         // Note: If we followed a CNAME with no dnssec protection, it is even more important that
2753         // we disable validation as we don't want to deliver a "secure" dnssec response later e.g.,
2754         // it is possible that the CNAME is not secure but the address records are secure. In this
2755         // case, we don't want to deliver the secure response later as we followed a CNAME that was
2756         // not protected with DNSSEC.
2757
2758         q->ValidationRequired = 0;
2759         q->ValidationState = DNSSECValNotRequired;
2760         
2761         if (FollowCNAME(q, answer, QC_add))
2762         {
2763             LogDNSSEC("DNSSECNoResponse: Following CNAME for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2764
2765             mDNS_Lock(m); 
2766             AnswerQuestionByFollowingCNAME(m, q, answer);
2767             mDNS_Unlock(m);
2768         }
2769
2770         if (m->ValidationQuestion == q)    // If m->ValidationQuestion was not auto-advanced, do it ourselves now
2771             m->ValidationQuestion = q->next;
2772     }
2773     m->ValidationQuestion = mDNSNULL;
2774
2775 done:
2776     FreeDNSSECVerifier(m, dv);
2777 }
2778
2779 mDNSlocal void DNSSECPositiveValidationCB(mDNS *const m, DNSSECVerifier *dv, CacheGroup *cg, ResourceRecord *answer, DNSSECStatus status)
2780 {
2781     RRVerifier *rrset;
2782     RRVerifier *rv;
2783     CacheRecord *cr;
2784     mDNSu16 rrtype, rrclass;
2785     CacheRecord *const lrr = &largerec.r;
2786
2787     LogDNSSEC("DNSSECPositiveValidationCB: called %s for %##s (%s)", DNSSECStatusName(status), dv->origName.c, DNSTypeName(dv->origType));
2788
2789     //
2790     // 1. Check to see if the rrset that was validated is the same as in cache. If they are not same,
2791     //    this validation result is not valid. When the rrset changed while the validation was in
2792     //    progress, the act of delivering the changed rrset again should have kicked off another
2793     //    verification.
2794     //
2795     // 2. Walk the question list to find the matching question. The original question that started
2796     //    the DNSSEC verification may or may not be there. As long as there is a matching question
2797     //    and waiting for the response, deliver the response.
2798     //
2799     // 3. If we are answering with CNAME, it is time to follow the CNAME if the response is secure
2800
2801     if (!dv->ac || status == DNSSEC_Insecure)
2802     {
2803         // For Insecure status, the auth chain contains information about the trust
2804         // chain starting from the known trust anchor. The rrsets are not related to
2805         // the origName like in Bogus or Secure.
2806         if (!answer)
2807             LogMsg("DNSSECPositiveValidationCB: ERROR: answer NULL");
2808     }
2809     else
2810     {
2811         if (!dv->ac->rrset)
2812         {
2813             LogMsg("DNSSECPositiveValidationCB: ERROR!! Validated RRSET NULL");
2814             goto done;
2815         }
2816
2817         rrset = dv->ac->rrset;
2818         rrtype = rrset->rrtype;
2819         rrclass = rrset->rrclass;
2820     
2821         lrr->resrec.name = &largerec.namestorage;
2822
2823         for (rv = dv->ac->rrset; rv; rv = rv->next)
2824             rv->found = 0;
2825
2826         // Check to see if we can find all the elements in the rrset
2827         for (cr = cg ? cg->members : mDNSNULL; cr; cr = cr->next)
2828         {
2829             if (cr->resrec.rrtype == rrtype && cr->resrec.rrclass == rrclass)
2830             {
2831                 for (rv = dv->ac->rrset; rv; rv = rv->next)
2832                 {
2833                     if (rv->rdlength == cr->resrec.rdlength && rv->rdatahash == cr->resrec.rdatahash)
2834                     {
2835                         lrr->resrec.namehash = rv->namehash;
2836                         lrr->resrec.rrtype = rv->rrtype;
2837                         lrr->resrec.rrclass = rv->rrclass;
2838                         lrr->resrec.rdata = (RData*)&lrr->smallrdatastorage;
2839                         lrr->resrec.rdata->MaxRDLength = MaximumRDSize;
2840
2841                         // Convert the "rdata" to a suitable form before we can call SameRDataBody which expects
2842                         // some of the resource records in host order and also domainnames fully expanded. We
2843                         // converted the resource records into network order for verification purpose and hence
2844                         // need to convert them back again before comparing them.
2845                         if (!SetRData(mDNSNULL, rv->rdata, rv->rdata + rv->rdlength, &largerec, rv->rdlength))
2846                         {
2847                             LogMsg("DNSSECPositiveValidationCB: SetRData failed for %##s (%s)", rv->name.c, DNSTypeName(rv->rrtype));
2848                         }
2849                         else if (SameRDataBody(&cr->resrec, &lrr->resrec.rdata->u, SameDomainName))
2850                         {
2851                             answer = &cr->resrec;
2852                             rv->found = 1;
2853                             break;
2854                         }
2855                     }
2856                 }
2857                 if (!rv)
2858                 {
2859                     // The validated rrset does not have the element in the cache, re-validate
2860                     LogDNSSEC("DNSSECPositiveValidationCB: CacheRecord %s, not found in the validated set", CRDisplayString(m, cr));
2861                     goto done;
2862                 }
2863             }
2864         }
2865         // Check to see if we have elements that were not in the cache
2866         for (rv = dv->ac->rrset; rv; rv = rv->next)
2867         {
2868             if (!rv->found)
2869             {
2870                 // We had more elements in the validated set, re-validate
2871                 LogDNSSEC("DNSSECPositiveValidationCB: Record %##s (%s) not found in the cache", rv->name.c, DNSTypeName(rv->rrtype));
2872                 goto done;
2873             }
2874         }
2875     }
2876
2877     // It is not an error for things to disappear underneath
2878     if (!answer)
2879     {
2880         LogDNSSEC("DNSSECPositiveValidationCB: answer NULL for %##s, %s", dv->origName.c, DNSTypeName(dv->origType));
2881         goto done;
2882     }
2883
2884     DeliverDNSSECStatus(m, dv, answer, status);
2885     SetTTLRRSet(m, dv, status);
2886
2887 done:
2888     FreeDNSSECVerifier(m, dv);
2889 }
2890
2891 mDNSlocal void DNSSECNegativeValidationCB(mDNS *const m, DNSSECVerifier *dv, CacheGroup *cg, ResourceRecord *answer, DNSSECStatus status)
2892 {
2893     RRVerifier *rv;
2894     CacheRecord *cr;
2895     mDNSu16 rrtype, rrclass;
2896     AuthChain *ac;
2897
2898     LogDNSSEC("DNSSECNegativeValidationCB: called %s for %##s (%s)", DNSSECStatusName(status), dv->origName.c, DNSTypeName(dv->origType));
2899
2900     if (dv->parent)
2901     {
2902         // When NSEC/NSEC3s validation is completed, it calls the parent's DVCallback with the
2903         // parent DNSSECVerifier which is the original one that started the verification. It itself
2904         // should not have a parent. If the NSEC/NSEC3 validation results in another NSEC/NSEC3
2905         // validation, it should chain up via the dv->parent all the way to the top.
2906         LogMsg("DNSSECNegativeValidationCB: ERROR!! dv->parent is set for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2907         goto done;
2908     }
2909
2910     // 1. Locate the negative cache record and check the cached NSEC/NSEC3 records to see if it matches the
2911     //    NSEC/NSEC3s that were valiated. If the cached NSEC/NSEC3s changed while the validation was in progress,
2912     //    we ignore the validation results.
2913     //
2914     // 2. Walk the question list to find the matching question. The original question that started
2915     //    the DNSSEC verification may or may not be there. As long as there is a matching question
2916     //    and waiting for the response, deliver the response.
2917     //
2918     if (!dv->ac || status == DNSSEC_Insecure)
2919     {
2920         // For Insecure status, the auth chain contains information about the trust
2921         // chain starting from the known trust anchor. The rrsets are not related to
2922         // the origName like in Bogus or Secure.
2923         if (!answer)
2924             LogMsg("DNSSECNegativeValidationCB: ERROR: answer NULL");
2925     }
2926     else
2927     {
2928         if (!dv->ac->rrset)
2929         {
2930             LogMsg("DNSSECNegativeValidationCB: ERROR!! Validated RRSET NULL");
2931             goto done;
2932         }
2933
2934         rrtype = dv->origType;
2935         rrclass = dv->ac->rrset->rrclass;
2936
2937         for (ac = dv->ac; ac; ac = ac->next)
2938         {
2939             for (rv = ac->rrset; rv; rv = rv->next)
2940             {
2941                 if (rv->rrtype == kDNSType_NSEC || rv->rrtype == kDNSType_NSEC3)
2942                 {
2943                     LogDNSSEC("DNSSECNegativeValidationCB: Record %p %##s (%s) marking zero", rv, rv->name.c, DNSTypeName(rv->rrtype));
2944                     rv->found = 0;
2945                 }
2946             }
2947         }
2948
2949         // Check to see if we can find all the elements in the rrset
2950         for (cr = cg->members; cr; cr = cr->next)
2951         {
2952             if (cr->resrec.RecordType == kDNSRecordTypePacketNegative && 
2953                 cr->resrec.rrtype == rrtype && cr->resrec.rrclass == rrclass)
2954             {
2955                 CacheRecord *ncr;
2956                 for (ncr = cr->nsec; ncr; ncr = ncr->next)
2957                 {
2958                     // We have RRSIGs for the NSECs cached there too
2959                     if (ncr->resrec.rrtype != kDNSType_NSEC && ncr->resrec.rrtype != kDNSType_NSEC3)
2960                         continue;
2961                     for (ac = dv->ac; ac; ac = ac->next)
2962                     {
2963                         for (rv = ac->rrset; rv; rv = rv->next)
2964                         {
2965                             if ((rv->rrtype == kDNSType_NSEC || rv->rrtype == kDNSType_NSEC3) && rv->rdlength == ncr->resrec.rdlength &&
2966                                 rv->rdatahash == ncr->resrec.rdatahash)
2967                             {
2968                                 if (SameDomainName(ncr->resrec.name, &rv->name) &&
2969                                     SameRDataBody(&ncr->resrec, (const RDataBody *)rv->rdata, SameDomainName))
2970                                 {
2971                                     LogDNSSEC("DNSSECNegativeValidationCB: Record %p %##s (%s) marking one", rv, rv->name.c, DNSTypeName(rv->rrtype));
2972                                     answer = &cr->resrec;
2973                                     rv->found = 1;
2974                                     break;
2975                                 }
2976                             }
2977                         }
2978                         if (rv)
2979                             break;
2980                     }
2981                 }
2982                 if (!rv)
2983                 {
2984                     // The validated rrset does not have the element in the cache, re-validate
2985                     LogDNSSEC("DNSSECNegativeValidationCB: CacheRecord %s, not found in the validated set", CRDisplayString(m, cr));
2986                     goto done;
2987                 }
2988             }
2989         }
2990         // Check to see if we have elements that were not in the cache
2991         for (ac = dv->ac; ac; ac = ac->next)
2992         {
2993             for (rv = ac->rrset; rv; rv = rv->next)
2994             {
2995                 if (rv->rrtype == kDNSType_NSEC || rv->rrtype == kDNSType_NSEC3)
2996                 {
2997                     if (!rv->found)
2998                     {
2999                         // We had more elements in the validated set, re-validate
3000                         LogDNSSEC("DNSSECNegativeValidationCB: Record %p %##s (%s) not found in the cache", rv, rv->name.c, DNSTypeName(rv->rrtype));
3001                         goto done;
3002                     }
3003                     rv->found = 0;
3004                 }
3005             }
3006         }
3007     }
3008
3009     // It is not an error for things to disappear underneath
3010     if (!answer)
3011     {
3012         LogDNSSEC("DNSSECNegativeValidationCB: answer NULL for %##s, %s", dv->origName.c, DNSTypeName(dv->origType));
3013         goto done;
3014     }
3015
3016     DeliverDNSSECStatus(m, dv, answer, status); 
3017     SetTTLRRSet(m, dv, status);
3018
3019 done:
3020     FreeDNSSECVerifier(m, dv);
3021 }
3022
3023 mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
3024 {
3025     mDNSu32 namehash;
3026     CacheGroup *cg;
3027     CacheRecord *cr;
3028
3029     LogDNSSEC("DNSSECValidationCB: called %s for %##s (%s)", DNSSECStatusName(status), dv->origName.c, DNSTypeName(dv->origType));
3030
3031     // Currently, if we receive anything other than secure, we abort DNSSEC validation for
3032     // the optional case.
3033     if (dv->ValidationRequired == DNSSEC_VALIDATION_SECURE_OPTIONAL && status != DNSSEC_Secure)
3034     {
3035         DNSSECNoResponse(m, dv);
3036         return; 
3037     }
3038
3039     if (dv->ValidationRequired == DNSSEC_VALIDATION_SECURE && !dv->InsecureProofDone && status == DNSSEC_Bogus)
3040     {
3041         dv->InsecureProofDone = 1;
3042         ProveInsecure(m, dv, mDNSNULL, mDNSNULL);
3043         return;
3044     }
3045     namehash = DomainNameHashValue(&dv->origName);
3046
3047     cg = CacheGroupForName(m, namehash, &dv->origName);
3048     if (!cg)
3049     {
3050         LogDNSSEC("DNSSECValidationCB: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
3051         FreeDNSSECVerifier(m, dv);
3052         return;
3053     }
3054     InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->origName, dv->origType, mDNSNULL, mDNSNULL);
3055     // Need to be reset ValidatingResponse as we are looking for the cache record that would answer
3056     // the original question
3057     dv->q.ValidatingResponse = mDNSfalse;
3058     for (cr = cg->members; cr; cr = cr->next)
3059     {
3060         if (SameNameRecordAnswersQuestion(&cr->resrec, &dv->q))
3061         {
3062             if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
3063                 DNSSECNegativeValidationCB(m, dv, cg, &cr->resrec, status);
3064             else
3065                 DNSSECPositiveValidationCB(m, dv, cg, &cr->resrec, status);
3066             return;
3067         }
3068     }
3069 }
3070
3071 mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
3072 {
3073     CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
3074     CacheRecord *rr;
3075     mDNSBool first = mDNSfalse;
3076     static mDNSBool TrustAnchorsUpdated = mDNSfalse;
3077
3078     LogDNSSEC("VerifySignature called for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3079     if (!TrustAnchorsUpdated)
3080     {
3081         TrustAnchorsUpdated = mDNStrue;
3082         UpdateTrustAnchors(m);
3083     }
3084     if (!dv)
3085     {
3086         first = mDNStrue;
3087         if (!q->qDNSServer || q->qDNSServer->cellIntf)
3088         {
3089             LogDNSSEC("VerifySignature: Disabled");
3090             return;
3091         }
3092         // We assume that the verifier's question has been initialized here so that ValidateWithNSECS below
3093         // knows what it has prove the non-existence of.
3094         dv = AllocateDNSSECVerifier(m, &q->qname, q->qtype, q->InterfaceID, q->ValidationRequired, DNSSECValidationCB, VerifySigCallback);
3095         if (!dv)
3096         {
3097             LogMsg("VerifySignature: ERROR!! memory alloc failed");
3098             return;
3099         }
3100     }
3101
3102     // If we find a CNAME response to the question, remember what qtype
3103     // caused the CNAME response. origType is not sufficient as we
3104     // recursively validate the response and origType is initialized above
3105     // the first time this function is called.
3106     dv->currQtype = q->qtype;
3107
3108     // Walk the cache and get all the rrsets for verification.
3109     for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
3110         if (SameNameRecordAnswersQuestion(&rr->resrec, q))
3111         {
3112             // We also get called for RRSIGs which matches qtype. We don't need that here as we are
3113             // building rrset for matching q->qname. Checking for RRSIG type is important as otherwise
3114             // we would miss the CNAME answering any qtype.
3115             if (rr->resrec.rrtype == kDNSType_RRSIG && rr->resrec.rrtype != q->qtype)
3116             {
3117                 LogDNSSEC("VerifySignature: Question %##s (%s) answered with RRSIG record %s, not using it", q->qname.c, DNSTypeName(q->qtype), CRDisplayString(m, rr));
3118                 continue;
3119             }
3120
3121             // See DNSSECRecordAnswersQuestion: This should never happen. NSEC records are
3122             // answered directly only when the qtype is NSEC. Otherwise, NSEC records are
3123             // used only for denial of existence and hence should go through negative cache
3124             // entry.
3125             if (rr->resrec.rrtype == kDNSType_NSEC && q->qtype != kDNSType_NSEC)
3126             {
3127                 LogMsg("VerifySignature: ERROR!! Question %##s (%s) answered using NSEC record %s", q->qname.c, DNSTypeName(q->qtype), CRDisplayString(m, rr));
3128                 continue;
3129             }
3130
3131             // We might get a NSEC response when we first send the query out from the "core" for ValidationRequired
3132             // questions. Later as part of validating the response, we might get a NSEC response.
3133             if (rr->resrec.RecordType == kDNSRecordTypePacketNegative && DNSSECQuestion(q))
3134             {
3135                 // If we can't find the NSEC, we can't validate. This can happens if we are
3136                 // behind a non-DNSSEC aware CPE/server.
3137                 if (!rr->nsec)
3138                 {
3139                     LogDNSSEC("VerifySignature: No nsecs found for %s", CRDisplayString(m, rr));
3140                     dv->DVCallback(m, dv, DNSSEC_Bogus);
3141                     return;
3142                 }
3143                 ValidateWithNSECS(m, dv, rr);
3144                 return;
3145             }
3146
3147             if (AddRRSetToVerifier(dv, &rr->resrec, mDNSNULL, RRVS_rr) != mStatus_NoError)
3148             {
3149                 dv->DVCallback(m, dv, DNSSEC_Bogus);
3150                 return;
3151             }
3152         }
3153     if (!dv->rrset)
3154     {
3155         LogMsg("VerifySignature: rrset mDNSNULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
3156         dv->DVCallback(m, dv, DNSSEC_Bogus);
3157         return;
3158     }
3159     dv->next = RRVS_rrsig;
3160     // Delay this so that the mDNS "core" can deliver all the results before
3161     // we can deliver the dnssec result
3162     if (first)
3163     {
3164         mDNSPlatformDispatchAsync(m, dv, StartDNSSECVerification);
3165     }
3166     else
3167     {
3168         StartDNSSECVerification(m, dv);
3169     }
3170 }
3171
3172 mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv)
3173 {
3174     rdataDS *ds;
3175     rdataDNSKey *key;
3176     TrustAnchor *ta;
3177     RRVerifier *keyv;
3178
3179     // Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies
3180     // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
3181     // this zone. Loop till we find one.
3182     for (ta = m->TrustAnchors; ta; ta = ta->next)
3183     {
3184         ds = (rdataDS *)&ta->rds;
3185         if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
3186         {
3187             LogMsg("TrustedKeyPresent: Unsupported digest %d", ds->digestType);
3188             continue;
3189         }
3190         else
3191         {
3192             debugdnssec("TrustedKeyPresent: digest type %d", ds->digestType);
3193         }
3194         for (keyv = dv->key; keyv; keyv = keyv->next)
3195         {
3196             key = (rdataDNSKey *)keyv->rdata;
3197             mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
3198             if (tag != ds->keyTag)
3199             {
3200                 debugdnssec("TrustedKeyPresent:Not a valid keytag %d", tag);
3201                 continue;
3202             }
3203             if (!SameDomainName(&keyv->name, &ta->zone))
3204             {
3205                 debugdnssec("TrustedKeyPresent: domainame mismatch key %##s, ta %##s", keyv->name.c, ta->zone.c);
3206                 continue;
3207             }
3208             return mDNStrue;
3209         }
3210     }
3211     return mDNSfalse;
3212 }
3213
3214 mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv)
3215 {
3216     mDNSu8 *digest;
3217     int digestLen;
3218     domainname name;
3219     rdataRRSig *rrsig;
3220     rdataDS *ds;
3221     rdataDNSKey *key;
3222     TrustAnchor *ta;
3223     RRVerifier *keyv;
3224     mStatus algRet;
3225     mDNSu32 currTime = mDNSPlatformUTC();
3226
3227     rrsig = (rdataRRSig *)dv->rrsig->rdata;
3228
3229     // Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies
3230     // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
3231     // this zone. Loop till we find one.
3232     for (ta = m->TrustAnchors; ta; ta = ta->next)
3233     {
3234         ds = (rdataDS *)&ta->rds;
3235         if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
3236         {
3237             LogMsg("TrustedKey: Unsupported digest %d", ds->digestType);
3238             continue;
3239         }
3240         else
3241         {
3242             debugdnssec("TrustedKey: Zone %##s, digest type %d, tag %d", ta->zone.c, ds->digestType, ds->keyTag);
3243         }
3244         for (keyv = dv->key; keyv; keyv = keyv->next)
3245         {
3246             key = (rdataDNSKey *)keyv->rdata;
3247             mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
3248             if (tag != ds->keyTag)
3249             {
3250                 debugdnssec("TrustedKey:Not a valid keytag %d", tag);
3251                 continue;
3252             }
3253             if (!SameDomainName(&keyv->name, &ta->zone))
3254             {
3255                 debugdnssec("TrustedKey: domainame mismatch key %##s, ta %##s", keyv->name.c, ta->zone.c);
3256                 continue;
3257             }
3258             if (DNS_SERIAL_LT(ta->validUntil, currTime))
3259             {
3260                 LogDNSSEC("TrustedKey: Expired: currentTime %d, ExpireTime %d", (int)currTime, ta->validUntil);
3261                 continue;
3262             }
3263             if (DNS_SERIAL_LT(currTime, ta->validFrom))
3264             {
3265                 LogDNSSEC("TrustedKey: Future: currentTime %d, InceptTime %d", (int)currTime, ta->validFrom);
3266                 continue;
3267             }
3268
3269             if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &name) != mStatus_NoError)
3270             {
3271                 LogMsg("TrustedKey: ERROR!! cannot convert to lower case");
3272                 continue;
3273             }
3274
3275             if (dv->ctx) AlgDestroy(dv->ctx);
3276             dv->ctx = AlgCreate(DIGEST_ALG, ds->digestType);
3277             if (!dv->ctx)
3278             {
3279                 LogMsg("TrustedKey: ERROR!! No digest support");
3280                 continue;
3281             }
3282             digest = ds->digest;
3283             digestLen = ta->digestLen;
3284
3285             AlgAdd(dv->ctx, name.c, DomainNameLength(&name));
3286             AlgAdd(dv->ctx, (const mDNSu8 *)key, keyv->rdlength);
3287
3288             algRet = AlgVerify(dv->ctx, mDNSNULL, 0, digest, digestLen);
3289             AlgDestroy(dv->ctx);
3290             dv->ctx = mDNSNULL;
3291             if (algRet == mStatus_NoError)
3292             {
3293                 LogDNSSEC("TrustedKey: DS Validated Successfully, need to verify the key %d", tag);
3294                 // We found the DNS KEY that is authenticated by the DS in our parent zone. Check to see if this key
3295                 // was used to sign the DNS KEY RRSET. If so, then the keys in our DNS KEY RRSET are valid
3296                 if (ValidateSignatureWithKeyForAllRRSigs(dv, dv->key, keyv, dv->rrsigKey))
3297                 {
3298                     LogDNSSEC("TrustedKey: DS Validated Successfully %d", tag);
3299                     return mStatus_NoError;
3300                 }
3301             }
3302         }
3303     }
3304     return mStatus_NoSuchRecord;
3305 }
3306
3307 mDNSlocal CacheRecord* NegativeCacheRecordForRR(mDNS *const m, const ResourceRecord *const rr)
3308 {
3309     mDNSu32 namehash;
3310     CacheGroup *cg;
3311     CacheRecord *cr;
3312
3313     namehash = DomainNameHashValue(rr->name);
3314     cg = CacheGroupForName(m, namehash, rr->name);
3315     if (!cg)
3316     {
3317         LogMsg("NegativeCacheRecordForRR: cg null %##s", rr->name->c);
3318         return mDNSNULL;
3319     }
3320     for (cr=cg->members; cr; cr=cr->next)
3321     {
3322         if (cr->resrec.RecordType == kDNSRecordTypePacketNegative && (&cr->resrec == rr))
3323             return cr;
3324     }
3325     return mDNSNULL;
3326 }
3327
3328 mDNSlocal void VerifySigCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
3329 {
3330     DNSSECVerifier *dv = (DNSSECVerifier *)question->QuestionContext;
3331     mDNSu16 rrtype;
3332     CacheRecord *negcr;
3333
3334     debugdnssec("VerifySigCallback: AddRecord %d, dv %p", AddRecord, dv);
3335
3336     if (!AddRecord)
3337         return;
3338
3339     // After the first ADD event, we should ideally stop the question. If we don't stop
3340     // the question, we might get more callbacks and that can cause problems. For example,
3341     // in the first callback, we could start a insecure proof and while that is in progress,
3342     // if we get more callbacks, we will try to start another insecure proof. As we already
3343     // started an insecure proof, we won't start another but terminate the verification
3344     // process where we free the current DNSSECVerifier while the first insecure proof is
3345     // still referencing it.
3346     //
3347     // But there are cases below which might return if we have not received the right answer
3348     // yet e.g., no RRSIGs. In that case if the question is stopped, we will never get any
3349     // callbacks again and also we leak "dv". Hence it is important that we either process
3350     // the result or wait for more results. Note that the question eventually times out
3351     // and cleans up the "dv" i.e., we don't wait forever.
3352     
3353     if (!answer)
3354     {
3355         LogDNSSEC("VerifySigCallback: Question %##s (%s) no dnssec response", question->qname.c, DNSTypeName(question->qtype));
3356         mDNS_StopQuery(m, question);
3357         dv->DVCallback(m, dv, DNSSEC_Bogus);
3358         return;
3359     }
3360
3361     LogDNSSEC("VerifySigCallback(%p): Called with record %s for question %##s (%s)", dv, RRDisplayString(m, answer), question->qname.c,
3362         DNSTypeName(question->qtype));
3363     mDNS_Lock(m);
3364     if ((m->timenow - question->StopTime) >= 0)
3365     {
3366         mDNS_Unlock(m);
3367         LogDNSSEC("VerifySigCallback: Question %##s (%s) timed out", question->qname.c, DNSTypeName(question->qtype));
3368         mDNS_StopQuery(m, question);
3369         dv->DVCallback(m, dv, DNSSEC_Bogus);
3370         return;
3371     }
3372     mDNS_Unlock(m);
3373
3374     if (answer->RecordType == kDNSRecordTypePacketNegative)
3375     {
3376         CacheRecord *cr;
3377         LogDNSSEC("VerifySigCallback: Received a negative answer with record %s, AddRecord %d",
3378                   RRDisplayString(m, answer), AddRecord);
3379         mDNS_StopQuery(m, question);
3380         cr = NegativeCacheRecordForRR(m, answer);
3381         if (cr && cr->nsec)
3382         {
3383             ValidateWithNSECS(m, dv, cr);
3384         }
3385         else
3386         {
3387             
3388             LogDNSSEC("VerifySigCallback: Missing record (%s) Negative Cache Record %p", RRDisplayString(m, answer), cr);
3389             dv->DVCallback(m, dv, DNSSEC_Bogus);
3390         }
3391         return;
3392     }
3393
3394     if (!dv->rrset)
3395     {
3396         LogMsg("VerifySigCallback: ERROR!! rrset NULL");
3397         mDNS_StopQuery(m, question);
3398         dv->DVCallback(m, dv, DNSSEC_Bogus);
3399         return;
3400     }
3401
3402     rrtype = answer->rrtype;
3403     // Check whether we got any answers for the question. If there are no answers, we
3404     // can't do the verification.
3405     //
3406     // We need to look at the whole rrset for verifying the signatures. This callback gets
3407     // called back for each record in the rrset sequentially and we won't know when to start the
3408     // verification. Hence, we look for all the records in the rrset ourselves using the
3409     // CheckXXX function below. The caller has to ensure that all the records in the rrset are
3410     // added to the cache before calling this callback which happens naturally because all
3411     // unicast records are marked for DelayDelivery and hence added to the cache before the
3412     // callback is done.
3413     //
3414     // We also need the RRSIGs for the rrset to do the validation. It is possible that the
3415     // cache contains RRSIG records but it may not be a valid record when we filter them
3416     // in CheckXXX function. For example, some application can query for RRSIG records which
3417     // might come back with a partial set of RRSIG records from the recursive server and
3418     // they may not be the right ones for the current validation. In this case, we still
3419     // need to send the query out to get the right RRSIGs but the "core" should not answer
3420     // this query with the same records that we checked and found them to be unusable.
3421     //
3422     // We handle this in two ways:
3423     //
3424     // 1) AnswerNewQuestion always sends the "ValidatingResponse" query out bypassing the cache.
3425     //
3426     // 2) DNSSECRecordAnswersQuestion does not answer a question with RRSIGs matching the
3427     //    same name as the query until the typeCovered also matches the query's type.
3428     //
3429     // NOTE: We use "next - 1" as next always points to what we are going to fetch next and not the one
3430     // we are fetching currently
3431     switch(dv->next - 1)
3432     {
3433     case RRVS_rr:
3434         // Verification always starts at RRVS_rrsig (which means dv->next points at RRVS_key) as verification does
3435         // not begin until we have the main rrset.
3436         LogDNSSEC("VerifySigCallback: ERROR!! rrset %##s dv->next is RRVS_rr", dv->rrset->name.c);
3437         return;
3438     case RRVS_rrsig:
3439         // We can get called back with rrtype matching qtype as new records are added to the cache
3440         // triggered by other questions. This could potentially mean that the rrset that is being
3441         // validated by this "dv" whose rrsets were initialized at the beginning of the verification
3442         // may not be the right one. If this case happens, we will detect this at the end of validation
3443         // and throw away the validation results. This should not be a common case.
3444         if (rrtype != kDNSType_RRSIG)
3445         {
3446             LogDNSSEC("VerifySigCallback: RRVS_rrsig called with %s", RRDisplayString(m, answer));
3447             return;
3448         }
3449         mDNS_StopQuery(m, question);
3450         if (CheckRRSIGForRRSet(m, dv, &negcr) != mStatus_NoError)
3451         {
3452             LogDNSSEC("VerifySigCallback: Unable to find RRSIG for %##s (%s), question %##s", dv->rrset->name.c,
3453                       DNSTypeName(dv->rrset->rrtype), question->qname.c);
3454             dv->DVCallback(m, dv, DNSSEC_Bogus);
3455             return;
3456         }
3457         break;
3458     case RRVS_key:
3459         // We are waiting for the DNSKEY record and hence dv->key should be NULL. If RRSIGs are being
3460         // returned first, ignore them for now.
3461         if (dv->key)
3462             LogDNSSEC("VerifySigCallback: ERROR!! RRVS_key dv->key non-NULL for %##s", question->qname.c);
3463         if (rrtype == kDNSType_RRSIG)
3464         {
3465             LogDNSSEC("VerifySigCallback: RRVS_key rrset type %s, %##s received before DNSKEY", DNSTypeName(rrtype), question->qname.c);
3466             return;
3467         }
3468         if (rrtype != question->qtype)
3469         {
3470             LogDNSSEC("VerifySigCallback: ERROR!! RRVS_key rrset type %s, %##s not matching qtype %d", DNSTypeName(rrtype), question->qname.c,
3471                 question->qtype);
3472             return;
3473         }
3474         mDNS_StopQuery(m, question);
3475         if (CheckKeyForRRSIG(m, dv, &negcr) != mStatus_NoError)
3476         {
3477             LogDNSSEC("VerifySigCallback: Unable to find DNSKEY for %##s (%s), question %##s", dv->rrset->name.c,
3478                       DNSTypeName(dv->rrset->rrtype), question->qname.c);
3479             dv->DVCallback(m, dv, DNSSEC_Bogus);
3480             return;
3481         }
3482         break;
3483     case RRVS_rrsig_key:
3484         // If we are in RRVS_rrsig_key, it means that we already found the relevant DNSKEYs (dv->key should be non-NULL).
3485         // If DNSKEY record is being returned i.e., it means it is being added to the cache, then it can't be in our
3486         // list.
3487         if (!dv->key)
3488             LogDNSSEC("VerifySigCallback: ERROR!! RRVS_rrsig_key dv->key NULL for %##s", question->qname.c);
3489         if (rrtype == question->qtype)
3490         {
3491             LogDNSSEC("VerifySigCallback: RRVS_rrsig_key rrset type %s, %##s", DNSTypeName(rrtype), question->qname.c);
3492             CheckOneKeyForRRSIG(dv, answer);
3493             return;
3494         }
3495         if (rrtype != kDNSType_RRSIG)
3496         {
3497             LogDNSSEC("VerifySigCallback: RRVS_rrsig_key rrset type %s, %##s not matching qtype %d", DNSTypeName(rrtype), question->qname.c,
3498                 question->qtype);
3499             return;
3500         }
3501         mDNS_StopQuery(m, question);
3502         if (CheckRRSIGForKey(m, dv, &negcr) != mStatus_NoError)
3503         {
3504             LogDNSSEC("VerifySigCallback: Unable to find RRSIG for %##s (%s), question %##s", dv->rrset->name.c,
3505                       DNSTypeName(dv->rrset->rrtype), question->qname.c);
3506             dv->DVCallback(m, dv, DNSSEC_Bogus);
3507             return;
3508         }
3509         break;
3510     case RRVS_ds:
3511         if (rrtype == question->qtype)
3512         {
3513             LogDNSSEC("VerifySigCallback: RRVS_ds rrset type %s, %##s", DNSTypeName(rrtype), question->qname.c);
3514         }
3515         else
3516         {
3517             LogDNSSEC("VerifySigCallback: RRVS_ds rrset type %s, %##s received before DS", DNSTypeName(rrtype), question->qname.c);
3518         }
3519         mDNS_StopQuery(m, question);
3520         // It is not an error if we don't find the DS record as we could have
3521         // a trusted key. Or this is not a secure delegation which will be handled
3522         // below.
3523         if (CheckDSForKey(m, dv, &negcr) != mStatus_NoError)
3524         {
3525             LogDNSSEC("VerifySigCallback: Unable find DS for %##s (%s), question %##s", dv->rrset->name.c,
3526                       DNSTypeName(dv->rrset->rrtype), question->qname.c);
3527         }
3528         // dv->next is already at RRVS_done, so if we "break" from here, we will end up
3529         // in FinishDNSSECVerification. We should not do that if we receive a negative
3530         // response. For all other cases above, GetAllRRSetsForVerification handles
3531         // negative cache record
3532         if (negcr)
3533         {
3534             if (!negcr->nsec)
3535             {
3536                 LogDNSSEC("VerifySigCallback: No nsec records for %##s (DS)", dv->ds->name.c);
3537                 dv->DVCallback(m, dv, DNSSEC_Bogus);
3538                 return;
3539             }
3540             ValidateWithNSECS(m, dv, negcr);
3541             return;
3542         }
3543         break;
3544     default:
3545         LogDNSSEC("VerifySigCallback: ERROR!! default case rrset %##s question %##s", dv->rrset->name.c, question->qname.c);
3546         mDNS_StopQuery(m, question);
3547         dv->DVCallback(m, dv, DNSSEC_Bogus);
3548         return;
3549     }
3550     if (dv->next != RRVS_done)
3551     {
3552         mDNSBool done = GetAllRRSetsForVerification(m, dv);
3553         if (done)
3554         {
3555             if (dv->next != RRVS_done)
3556                 LogMsg("VerifySigCallback ERROR!! dv->next is not done");
3557             else
3558                 LogDNSSEC("VerifySigCallback: all rdata sets available for sig verification");
3559         }
3560         else
3561         {
3562             LogDNSSEC("VerifySigCallback: all rdata sets not available for sig verification");
3563             return;
3564         }
3565     }
3566     FinishDNSSECVerification(m, dv);
3567 }
3568
3569 mDNSlocal TrustAnchor *FindTrustAnchor(mDNS *const m, const domainname *const name)
3570 {
3571     TrustAnchor *ta;
3572     TrustAnchor *matchTA = mDNSNULL;
3573     TrustAnchor *rootTA = mDNSNULL;
3574     int currmatch = 0;
3575     int match;
3576     mDNSu32 currTime = mDNSPlatformUTC();
3577
3578     for (ta = m->TrustAnchors; ta; ta = ta->next)
3579     {
3580         if (DNS_SERIAL_LT(ta->validUntil, currTime))
3581         {
3582             LogDNSSEC("FindTrustAnchor: Expired: currentTime %d, ExpireTime %d", (int)currTime, ta->validUntil);
3583             continue;
3584         }
3585         if (DNS_SERIAL_LT(currTime, ta->validFrom))
3586         {
3587             LogDNSSEC("FindTrustAnchor: Future: currentTime %d, InceptTime %d", (int)currTime, ta->validFrom);
3588             continue;
3589         }
3590
3591         if (SameDomainName((const domainname *)"\000", &ta->zone))
3592             rootTA = ta;
3593
3594         match = CountLabelsMatch(&ta->zone, name);
3595         if (match > currmatch)
3596         {
3597             currmatch = match;
3598             matchTA = ta;
3599         }
3600     }
3601     if (matchTA)
3602     {
3603         LogDNSSEC("FindTrustAnhcor: matched %##s", matchTA->zone.c);
3604         return matchTA;
3605     }
3606     else if (rootTA)
3607     {
3608         LogDNSSEC("FindTrustAnhcor: matched rootTA %##s", rootTA->zone.c);
3609         return rootTA;
3610     }
3611     else
3612     {
3613         LogDNSSEC("FindTrustAnhcor: No Trust Anchor");
3614         return mDNSNULL;
3615     }
3616 }
3617
3618 mDNSlocal void DeliverInsecureProofResultAsync(mDNS *const m, void *context)
3619 {
3620     InsecureContext *ic = (InsecureContext *)context;
3621     ic->dv->DVCallback(m, ic->dv, ic->status);
3622     if (ic->q.ThisQInterval != -1)
3623     {
3624         LogMsg("DeliverInsecureProofResultAsync: ERROR!! Question %##s (%s) not stopped already", ic->q.qname.c, DNSTypeName(ic->q.qtype));
3625         mDNS_StopQuery(m, &ic->q);
3626     }
3627     mDNSPlatformMemFree(ic);
3628 }
3629
3630 mDNSlocal void DeliverInsecureProofResult(mDNS *const m, InsecureContext *ic, DNSSECStatus status)
3631 {
3632     // If the status is Bogus, restore the original auth chain before the insecure
3633     // proof.
3634     if (status == DNSSEC_Bogus)
3635     {
3636         LogDNSSEC("DeliverInsecureProofResult: Restoring the auth chain");
3637         if (ic->dv->ac)
3638         {
3639             FreeDNSSECAuthChainInfo(ic->dv->ac);
3640         }
3641         ResetAuthChain(ic->dv);
3642         ic->dv->ac = ic->dv->saveac;
3643         if (ic->dv->ac)
3644         {
3645             AuthChain *tmp = ic->dv->ac;
3646             AuthChain **tail = &tmp->next;
3647             while (tmp->next)
3648             {
3649                 tail = &tmp->next;
3650                 tmp = tmp->next;
3651             }
3652             ic->dv->actail = tail;
3653         }
3654         ic->dv->saveac = mDNSNULL;
3655     }
3656     else if (ic->dv->saveac)
3657     {
3658         FreeDNSSECAuthChainInfo(ic->dv->saveac);
3659         ic->dv->saveac = mDNSNULL;
3660     }
3661     ic->status = status;
3662     // Stop the question before we schedule the block so that we don't receive additional
3663     // callbacks again. Once the block runs, it will free the "ic" and you can't
3664     // have another block queued up. This can happen if we receive a callback after we
3665     // queue the block below.
3666     if (ic->q.ThisQInterval != -1)
3667         mDNS_StopQuery(m, &ic->q);
3668     mDNSPlatformDispatchAsync(m, ic, DeliverInsecureProofResultAsync);
3669 }
3670
3671 mDNSlocal mDNSBool AlgorithmSupported(rdataDS *ds)
3672 {
3673     switch(ds->digestType)
3674     {
3675     case SHA1_DIGEST_TYPE:
3676     case SHA256_DIGEST_TYPE:
3677         break;
3678     default:
3679         LogDNSSEC("AlgorithmSupported: Unsupported digest %d", ds->digestType);
3680         return mDNSfalse;
3681     }
3682
3683     switch(ds->alg)
3684     {
3685     case CRYPTO_RSA_NSEC3_SHA1:
3686     case CRYPTO_RSA_SHA1:
3687     case CRYPTO_RSA_SHA256:
3688     case CRYPTO_RSA_SHA512:
3689         return mDNStrue;
3690     default:
3691         LogDNSSEC("AlgorithmSupported: Unsupported algorithm %d", ds->alg);
3692         return mDNSfalse;
3693     }
3694 }
3695
3696 // Note: This function is called when DNSSEC results are delivered (from DeliverDNSSECStatus) and we can't deliver DNSSEC result
3697 // again within this function as "m->ValidationQuestion" is already in use. Hence we should dispatch off the delivery of insecure
3698 // results asynchronously.
3699 //
3700 // Insecure proof callback can deliver either insecure or bogus, but never secure result.
3701 mDNSlocal void ProveInsecureCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
3702 {
3703     InsecureContext *ic = (InsecureContext *)question->QuestionContext;
3704     DNSSECVerifier *pdv = ic->dv;
3705     AuthChain *ac;
3706
3707     (void) answer;
3708
3709     if (!AddRecord)
3710         return;
3711
3712     mDNS_Lock(m);
3713     if ((m->timenow - question->StopTime) >= 0)
3714     {
3715         mDNS_Unlock(m);
3716         LogDNSSEC("ProveInsecureCallback: Question %##s (%s) timed out", question->qname.c, DNSTypeName(question->qtype));
3717         DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3718         return;
3719     }
3720     mDNS_Unlock(m);
3721
3722     // We only need to handle the actual DNSSEC results and the ones that are secure. Anything else results in
3723     // bogus.
3724     if (AddRecord != QC_dnssec)
3725     {
3726         LogDNSSEC("ProveInsecureCallback: Question %##s (%s), AddRecord %d, answer %s", question->qname.c,
3727             DNSTypeName(question->qtype), AddRecord, RRDisplayString(m, answer));
3728         return;
3729     }
3730
3731     LogDNSSEC("ProveInsecureCallback: ic %p Question %##s (%s), DNSSEC status %s", ic, question->qname.c, DNSTypeName(question->qtype),
3732             DNSSECStatusName(question->ValidationStatus));
3733
3734     // Insecure is delivered for NSEC3 OptOut 
3735     if (question->ValidationStatus != DNSSEC_Secure && question->ValidationStatus != DNSSEC_Insecure)
3736     {
3737         LogDNSSEC("ProveInsecureCallback: Question %##s (%s) returned DNSSEC status %s", question->qname.c,
3738             DNSTypeName(question->qtype), DNSSECStatusName(question->ValidationStatus));
3739         goto done;
3740     }
3741     ac = (AuthChain *)question->DNSSECAuthInfo;
3742     if (!ac)
3743     {
3744         LogDNSSEC("ProveInsecureCallback: ac NULL for question %##s, %s", question->qname.c, DNSTypeName(question->qtype));
3745         goto done;
3746     }
3747     if (!ac->rrset)
3748     {
3749         LogDNSSEC("ProveInsecureCallback: ac->rrset NULL for question %##s, %s", question->qname.c, DNSTypeName(question->qtype));
3750         goto done;
3751     }
3752     if (ac->rrset->rrtype != kDNSType_DS && ac->rrset->rrtype != kDNSType_NSEC && ac->rrset->rrtype != kDNSType_NSEC3)
3753     {
3754         LogDNSSEC("ProveInsecureCallback: ac->rrset->rrtype %##s (%s) not handled", ac->rrset->name.c,
3755             DNSTypeName(ac->rrset->rrtype));
3756         goto done;
3757     }
3758     AuthChainLink(pdv, ac);
3759     question->DNSSECAuthInfo = mDNSNULL;
3760     if (ac->rrset->rrtype == kDNSType_DS)
3761     {
3762         rdataDS *ds = (rdataDS *)ac->rrset->rdata;
3763
3764         // If the delegation is secure, but the underlying zone is signed with an unsupported
3765         // algorithm, then we can't verify it. Deliver insecure in that case.
3766         if (!AlgorithmSupported(ds))
3767         {
3768             LogDNSSEC("ProveInsecureCallback: Unsupported algorithm %d or digest %d", ds->alg, ds->digestType);
3769             DeliverInsecureProofResult(m, ic, DNSSEC_Insecure);
3770             return;
3771         }
3772
3773         // If the delegation is secure and the name that we queried for is same as the original
3774         // name that started the insecure proof, then something is not right. We started the
3775         // insecure proof e.g., the zone is not signed, but we are able to validate a DS for
3776         // the same name which implies that the zone is signed (whose algorithm we support) and
3777         // we should not have started the insecurity proof in the first place.
3778         if (SameDomainName(&question->qname, &pdv->origName))
3779         {
3780             LogDNSSEC("ProveInsecureCallback: Insecure proof reached original name %##s, error", question->qname.c);
3781             DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3782             return;
3783         }
3784
3785         LogDNSSEC("ProveInsecureCallback: Trying one more level down");
3786         ProveInsecure(m, pdv, ic, mDNSNULL);
3787     }
3788     else if (ac->rrset->rrtype == kDNSType_NSEC || ac->rrset->rrtype == kDNSType_NSEC3)
3789     {
3790         CacheRecord *cr;
3791
3792         if (ac->rrset->rrtype == kDNSType_NSEC)
3793             cr = NSECRecordIsDelegation(m, &question->qname, question->qtype);
3794         else
3795             cr = NSEC3RecordIsDelegation(m, &question->qname, question->qtype);
3796                 if (cr)
3797         {
3798             LogDNSSEC("ProveInsecureCallback: Non-existence proved and %s is a delegation for %##s (%s)", CRDisplayString(m, cr),
3799                                 question->qname.c, DNSTypeName(question->qtype));
3800             DeliverInsecureProofResult(m, ic, DNSSEC_Insecure);
3801                         return;
3802         }
3803         // Could be a ENT. Go one more level down to see whether it is a secure delegation or not.
3804         if (!SameDomainName(&question->qname, &pdv->origName))
3805         {
3806             LogDNSSEC("ProveInsecureCallback: Not a delegation %##s (%s), go one more level down", question->qname.c, DNSTypeName(question->qtype));
3807             ProveInsecure(m, pdv, ic, mDNSNULL);
3808         }
3809         else
3810         {
3811              // Secure denial of existence and the name matches the original query. This means we should have
3812              // received an NSEC (if the type does not exist) or signed records (if the name and type exists)
3813              // and verified it successfully instead of starting the insecure proof. This could happen e.g.,
3814              // Wildcard expanded answer received without NSEC/NSEC3s etc. Also, is it possible that the
3815              // zone went from unsigned to signed in a short time ? For now, we return bogus.
3816              LogDNSSEC("ProveInsecureCallback: Not a delegation %##s (%s), but reached original name", question->qname.c,
3817                  DNSTypeName(question->qtype));
3818              DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3819         }
3820     }
3821     return;
3822 done:
3823     DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3824 }
3825
3826 // We return Insecure if we don't have a trust anchor or we have a trust anchor and
3827 // can prove that the delegation is not secure (and hence can't establish the trust
3828 // chain) or the delegation is possibly secure but we don't have the algorithm support
3829 // to prove that.
3830 mDNSexport void ProveInsecure(mDNS *const m, DNSSECVerifier *dv, InsecureContext *ic, domainname *trigger)
3831 {
3832     TrustAnchor *ta;
3833     domainname *sname;
3834
3835     if (ic == mDNSNULL)
3836     {
3837         ic = (InsecureContext *)mDNSPlatformMemAllocate(sizeof(InsecureContext));
3838         if (!ic)
3839         {
3840             LogMsg("mDNSPlatformMemAllocate: ERROR!! memory alloc failed for ic");
3841             return;
3842         }
3843         
3844         // Save the AuthInfo while we are proving insecure. We don't want to mix up
3845         // the auth chain for Bogus and Insecure. If we prove it to be insecure, we
3846         // will add the chain corresponding to the insecure proof. Otherwise, we will
3847         // restore this chain.
3848         if (dv->ac)
3849         {
3850             if (!dv->saveac)
3851             {
3852                 LogDNSSEC("ProveInsecure: saving authinfo");
3853             }
3854             else
3855             {
3856                 LogDNSSEC("ProveInsecure: ERROR!! authinfo already set");
3857                 FreeDNSSECAuthChainInfo(dv->saveac);
3858             }
3859             dv->saveac = dv->ac;
3860             ResetAuthChain(dv);
3861         }
3862         ic->dv = dv;
3863         ic->q.ThisQInterval = -1;
3864
3865         if (trigger)
3866         {
3867             LogDNSSEC("ProveInsecure: Setting Trigger %##s", trigger->c);
3868             ic->triggerLabelCount = CountLabels(trigger);
3869         }
3870         else
3871         {
3872             LogDNSSEC("ProveInsecure: No Trigger");
3873             ic->triggerLabelCount = CountLabels(&dv->origName);
3874         }
3875
3876         ta = FindTrustAnchor(m, &dv->origName);
3877         if (!ta)
3878         {
3879             LogDNSSEC("ProveInsecure: TrustAnchor NULL");
3880             DeliverInsecureProofResult(m, ic, DNSSEC_Insecure);
3881             return;
3882         }
3883         // We want to skip the labels that is already matched by the trust anchor so
3884         // that the first query starts just below the trust anchor
3885         ic->skip = CountLabels(&dv->origName) - CountLabels(&ta->zone);
3886         if (!ic->skip)
3887         {
3888             LogDNSSEC("ProveInsecure: origName %##s, skip is zero", dv->origName.c);
3889             DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3890             return;
3891         }
3892     }
3893     // Look for the DS record starting just below the trust anchor.
3894     //
3895     // 1. If we find an NSEC record, then see if it is a delegation. If it is, then
3896     //    we are done. Otherwise, go down one more level.
3897     //
3898     // 2. If we find a DS record and no algorithm support, return "insecure". Otherwise, go
3899     //    down one more level.
3900     //
3901     sname = (domainname *)SkipLeadingLabels(&dv->origName, (ic->skip ? ic->skip - 1 : 0));
3902     if (!sname)
3903     {
3904         LogDNSSEC("ProveInsecure: sname NULL, origName %##s, skip %d", dv->origName.c, ic->skip);
3905         DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3906         return;
3907     }
3908
3909     // Insecurity proof is started during the normal bottom-up validation when we have a break in the trust
3910     // chain e.g., we get NSEC/NSEC3s when looking up a DS record. Insecurity proof is top-down looking
3911     // for a break in the trust chain. If we have already tried the validation (before the insecurity
3912     // proof started) for this "sname", then don't bother with the proof. This happens sometimes, when 
3913     // we can't prove whether a zone is insecurely delegated or not. For example, if we are looking up
3914     // host1.secure-nods.secure.example and when we encounter secure-nods, there is no DS record in the
3915     // parent. We start the insecurity proof remembering that "secure-nods.secure.example" is the trigger
3916     // point. As part of the proof we reach "secure-nods.secure.example". Even though secure.example
3917     // prove that the name "secure-nods.secure.example/DS" does not exist,  it can't prove that it is a
3918     // delegation. So, we continue one more level down to host1.secure-nods.secure.example and we
3919     // realize that we already tried the validation and hence abort here.
3920
3921     if (CountLabels(sname) > ic->triggerLabelCount)
3922     {
3923         LogDNSSEC("ProveInsecure: Beyond the trigger current name %##s, origName %##s", sname->c, dv->origName.c);
3924         DeliverInsecureProofResult(m, ic, DNSSEC_Bogus);
3925         return;
3926     }
3927
3928     LogDNSSEC("ProveInsecure: OrigName %##s (%s), Current %##s", dv->origName.c, DNSTypeName(dv->origType), sname->c);
3929     ic->skip--;
3930     InitializeQuestion(m, &ic->q, dv->InterfaceID, sname, kDNSType_DS, ProveInsecureCallback, ic);
3931     ic->q.ValidationRequired = DNSSEC_VALIDATION_INSECURE;
3932     ic->q.ValidatingResponse = 0;
3933     ic->q.DNSSECAuthInfo = mDNSNULL;
3934     mDNS_StartQuery(m, &ic->q);
3935 }
3936
3937 mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
3938 {
3939     switch (type)
3940     {
3941     case kStatsTypeMemoryUsage:
3942         if (action == kStatsActionIncrement)
3943         {
3944             m->DNSSECStats.TotalMemUsed += value;
3945         }
3946         else if (action == kStatsActionDecrement)
3947         {
3948             m->DNSSECStats.TotalMemUsed -= value;
3949         }
3950         break;
3951     case kStatsTypeLatency:
3952         if (action == kStatsActionSet)
3953         {
3954             if (value <= 4)
3955             {
3956                 m->DNSSECStats.Latency0++;
3957             }
3958             else if (value <= 9)
3959             {
3960                 m->DNSSECStats.Latency5++;
3961             }
3962             else if (value <= 19)
3963             {
3964                 m->DNSSECStats.Latency10++;
3965             }
3966             else if (value <= 49)
3967             {
3968                 m->DNSSECStats.Latency20++;
3969             }
3970             else if (value <= 99)
3971             {
3972                 m->DNSSECStats.Latency50++;
3973             }
3974             else
3975             {
3976                 m->DNSSECStats.Latency100++;
3977             }
3978         }
3979         break;
3980     case kStatsTypeExtraPackets:
3981         if (action == kStatsActionSet)
3982         {
3983             if (value <= 2)
3984             {
3985                 m->DNSSECStats.ExtraPackets0++;
3986             }
3987             else if (value <= 6)
3988             {
3989                 m->DNSSECStats.ExtraPackets3++;
3990             }
3991             else if (value <= 9)
3992             {
3993                 m->DNSSECStats.ExtraPackets7++;
3994             }
3995             else
3996             {
3997                 m->DNSSECStats.ExtraPackets10++;
3998             }
3999         }
4000         break;
4001     case kStatsTypeStatus:
4002         if (action == kStatsActionSet)
4003         {
4004             switch(value)
4005             {
4006             case DNSSEC_Secure:
4007                 m->DNSSECStats.SecureStatus++;
4008                 break;
4009             case DNSSEC_Insecure:
4010                 m->DNSSECStats.InsecureStatus++;
4011                 break;
4012             case DNSSEC_Indeterminate:
4013                 m->DNSSECStats.IndeterminateStatus++;
4014                 break;
4015             case DNSSEC_Bogus:
4016                 m->DNSSECStats.BogusStatus++;
4017                 break;
4018             case DNSSEC_NoResponse:
4019                 m->DNSSECStats.NoResponseStatus++;
4020                 break;
4021             default:
4022                 LogMsg("BumpDNSSECStats: unknown status %d", value);
4023             }
4024         }
4025         break;
4026     case kStatsTypeMsgSize:
4027         if (action == kStatsActionSet)
4028         {
4029             if (value <= 1024)
4030             {
4031                 m->DNSSECStats.MsgSize0++;
4032             }
4033             else if (value <= 2048)
4034             {
4035                 m->DNSSECStats.MsgSize1++;
4036             }
4037             else
4038             {
4039                 m->DNSSECStats.MsgSize2++;
4040             }
4041         }
4042         break;
4043     case kStatsTypeProbe:
4044         if (action == kStatsActionIncrement)
4045         {
4046             m->DNSSECStats.NumProbesSent += value;
4047         }
4048         break;
4049     default:
4050         LogMsg("BumpDNSSECStats: unknown type %d", type);
4051     }
4052     return;
4053 }
4054
4055 #else // !DNSSEC_DISABLED
4056
4057 mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
4058 {
4059     (void)m;
4060     (void)dv;
4061     (void)q;
4062 }
4063
4064 mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
4065 {
4066     (void)m;
4067     (void)action;
4068     (void)type;
4069     (void)value;
4070 }
4071
4072 mDNSexport void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname, mDNSu16 qtype, mDNSQuestionCallback *callback, void *context)
4073 {
4074     (void) m;
4075     (void) question;
4076     (void) InterfaceID;
4077     (void) qname;
4078     (void) qtype;
4079     (void) callback;
4080     (void) context;
4081 }
4082
4083 mDNSexport char *DNSSECStatusName(DNSSECStatus status)
4084 {
4085     (void) status;
4086     
4087     return mDNSNULL;
4088 }
4089
4090 #endif // !DNSSEC_DISABLED