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