]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSCore/dnssec.c
mDNSResponder-379.27.tar.gz
[apple/mdnsresponder.git] / mDNSCore / dnssec.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2011 Apple Computer, 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 #include "mDNSEmbeddedAPI.h"
18 #include "DNSCommon.h"
19 #include "dnssec.h"
20 #include "CryptoAlg.h"
21 #include "nsec.h"
22
23 //#define DNSSEC_DEBUG
24
25 #ifdef DNSSEC_DEBUG
26 #define debugdnssec LogMsg
27 #else
28 #define debugdnssec debug_noop
29 #endif
30 //
31 // Implementation Notes
32 //
33 // The entry point to DNSSEC Verification is VerifySignature. This function is called from the "core" when
34 // the answer delivered to the application needs DNSSEC validation. If a question needs DNSSEC
35 // validation, "ValidationRequired" would be set. As we need to issue more queries to validate the
36 // original question, we create another question as part of the verification process (question is part of
37 // DNSSECVerifier). This question sets "ValidatingResponse" to distinguish itself from the original
38 // question. Without this, it will be a duplicate and never sent out. The "core" almost treats both the
39 // types identically (like adding EDNS0 option with DO bit etc.) except for a few differences. When RRSIGs
40 // are added to the cache, "ValidatingResponse" question gets called back as long as the typeCovered matches
41 // the question's qtype. See the comment in DNSSECRecordAnswersQuestion for the details. The other big
42 // difference is that "ValidationRequired" question kicks off the verification process by calling into
43 // "VerifySignature" whereas ValidationResponse don't do that as it gets callback for its questions.
44 //
45 // VerifySignature does not retain the original question that started the verification process. It just
46 // remembers the name and the type. It takes a snapshot of the cache at that instance which will be
47 // verified using DNSSEC. If the cache changes subsequently e.g., network change etc., it will be detected
48 // when the validation is completed. If there is a change, it will be revalidated.
49 //
50 // The verification flow looks like this:
51 //
52 // VerifySignature -> StartDNSSECVerification - GetAllRRSetsForVerification -> FinishDNSSECVerification -> VerifySignature
53 //
54 // Verification is a recursive process. It stops when we find a trust anchor or if we have recursed too deep.
55 //
56 // If the original question resulted in NODATA/NXDOMAIN error, there should have been NSECs as part of the response.
57 // These nsecs are cached along with the negative cache record. These are validated using ValidateWithNSECS called
58 // from Verifysignature.
59 //
60 // The flow in this case looks like this:
61 //
62 // VerifySignature -> ValidateWithNSECS -> {NoDataProof, NameErrorProof} -> VerifyNSECS -> StartDNSSECVerification
63 //
64 // Once the DNSSEC verification is started, it is similar to the previous flow described above. When the verification
65 // is done, DNSSECPositiveValidationCB or DNSSECNegativeValidationCB will be called which will then deliver the
66 // validation results to the original question that started the validation.
67 //
68 // Forward declaration
69 mDNSlocal void VerifySigCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
70 mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv);
71 mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv);
72 mDNSlocal mStatus ValidateDS(DNSSECVerifier *dv);
73 mDNSlocal void DNSSECNegativeValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status);
74
75 // Currently we use this to convert a RRVerifier to resource record so that we can
76 // use the standard DNS utility functions
77 LargeCacheRecord largerec;
78
79 // Verification is a recursive process. We arbitrarily limit to 10 just to be cautious which should be
80 // removed in the future.
81 #define MAX_RECURSE_COUNT 10
82
83 // RFC 4034 Appendix B: Get the keyid of a DNS KEY. It is not transmitted
84 // explicitly on the wire.
85 //
86 // Note: This just helps narrow down the list of keys to look at. It is possible
87 // for two DNS keys to have the same ID i.e., key ID is not a unqiue tag
88 //
89 // 1st argument - the RDATA part of the DNSKEY RR
90 // 2nd argument - the RDLENGTH
91 //
92 mDNSlocal mDNSu32 keytag(mDNSu8 *key, mDNSu32 keysize)
93 {
94 unsigned long ac;
95 unsigned int i;
96
97 // DST_ALG_RSAMD5 will be rejected automatically as the keytag
98 // is calculated wrongly
99
100 for (ac = 0, i = 0; i < keysize; ++i)
101 ac += (i & 1) ? key[i] : key[i] << 8;
102 ac += (ac >> 16) & 0xFFFF;
103 return ac & 0xFFFF;
104 }
105
106 mDNSlocal int DNSMemCmp(mDNSu8 *const m1, mDNSu8 *const m2, int len)
107 {
108 int res;
109
110 res = mDNSPlatformMemCmp(m1, m2, len);
111 if (res != 0)
112 return (res < 0 ? -1 : 1);
113 return 0;
114 }
115
116 mDNSlocal mStatus DNSNameToLowerCase(domainname *d, domainname *result)
117 {
118 const mDNSu8 *a = d->c;
119 mDNSu8 *b = result->c;
120 const mDNSu8 *const max = d->c + MAX_DOMAIN_NAME;
121 int i, len;
122
123 while (*a)
124 {
125 if (a + 1 + *a >= max)
126 {
127 LogMsg("DNSNameToLowerCase: ERROR!! Malformed Domain name");
128 return mStatus_BadParamErr;
129 }
130 len = *a++;
131 *b++ = len;
132 for (i = 0; i < len; i++)
133 {
134 mDNSu8 ac = *a++;
135 if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
136 *b++ = ac;
137 }
138 }
139 *b = 0;
140
141 return mStatus_NoError;
142 }
143
144 // Initialize the question enough so that it can be answered from the cache using SameNameRecordAnswersQuestion or
145 // ResourceRecordAnswersQuestion.
146 mDNSexport void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname,
147 mDNSu16 qtype, mDNSQuestionCallback *callback, void *context)
148 {
149 LogOperation("InitializeQuestion: Called for %##s (%s)", qname->c, DNSTypeName(qtype));
150
151 if (question->ThisQInterval != -1) mDNS_StopQuery(m, question);
152
153 mDNS_SetupQuestion(question, InterfaceID, qname, qtype, callback, context);
154 question->qnamehash = DomainNameHashValue(qname);
155 question->ValidatingResponse = mDNStrue;
156
157 // We need to set the DNS server appropriately to match the question against the cache record.
158 // Though not all callers of this function need it, we always do it to keep it simple.
159 SetValidDNSServers(m, question);
160 question->qDNSServer = GetServerForQuestion(m, question);
161
162 // Make it look like unicast
163 question->TargetQID = onesID;
164 question->TimeoutQuestion = 1;
165 question->ReturnIntermed = 1;
166 // SetupQuestion sets LongLived if qtype == PTR
167 question->LongLived = 0;
168 }
169
170 mDNSexport DNSSECVerifier *AllocateDNSSECVerifier(mDNS *const m, const domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID,
171 DNSSECVerifierCallback dvcallback, mDNSQuestionCallback qcallback)
172 {
173 DNSSECVerifier *dv;
174
175 dv = (DNSSECVerifier *)mDNSPlatformMemAllocate(sizeof(DNSSECVerifier));
176 if (!dv) { LogMsg("AllocateDNSSECVerifier: ERROR!! memory alloc failed"); return mDNSNULL; }
177 mDNSPlatformMemZero(dv, sizeof(*dv));
178
179 // Remember the question's name and type so that when we are done processing all
180 // the verifications, we can trace the original question back
181 AssignDomainName(&dv->origName, name);
182 dv->origType = rrtype;
183 dv->InterfaceID = InterfaceID;
184 dv->DVCallback = dvcallback;
185 dv->q.ThisQInterval = -1;
186 dv->ac = mDNSNULL;
187 dv->actail = &dv->ac;
188 // The verifier's question has to be initialized as some of the callers assume it
189 InitializeQuestion(m, &dv->q, InterfaceID, name, rrtype, qcallback, dv);
190 return dv;
191 }
192
193 mDNSlocal void FreeDNSSECAuthChain(DNSSECVerifier *dv)
194 {
195 RRVerifier *rrset;
196 RRVerifier *next;
197 AuthChain *ac, *acnext;
198
199 LogDNSSEC("FreeDNSSECAuthChain: called");
200
201 ac = dv->ac;
202
203 while (ac)
204 {
205 acnext = ac->next;
206 rrset = ac->rrset;
207 while (rrset)
208 {
209 next = rrset->next;
210 mDNSPlatformMemFree(rrset);
211 rrset = next;
212 }
213 ac->rrset = mDNSNULL;
214
215 rrset = ac->rrsig;
216 while (rrset)
217 {
218 next = rrset->next;
219 mDNSPlatformMemFree(rrset);
220 rrset = next;
221 }
222 ac->rrsig = mDNSNULL;
223
224 rrset = ac->key;
225 while (rrset)
226 {
227 next = rrset->next;
228 mDNSPlatformMemFree(rrset);
229 rrset = next;
230 }
231 ac->key = mDNSNULL;
232
233 mDNSPlatformMemFree(ac);
234 ac = acnext;
235 }
236 dv->ac = mDNSNULL;
237 }
238
239 mDNSlocal void FreeDNSSECVerifierRRSets(DNSSECVerifier *dv)
240 {
241 RRVerifier *rrset;
242 RRVerifier *next;
243
244 //debugdnssec("FreeDNSSECVerifierRRSets called %p", dv);
245 rrset = dv->rrset;
246 while (rrset)
247 {
248 next = rrset->next;
249 mDNSPlatformMemFree(rrset);
250 rrset = next;
251 }
252 dv->rrset = mDNSNULL;
253
254 rrset = dv->rrsig;
255 while (rrset)
256 {
257 next = rrset->next;
258 mDNSPlatformMemFree(rrset);
259 rrset = next;
260 }
261 dv->rrsig = mDNSNULL;
262
263 rrset = dv->key;
264 while (rrset)
265 {
266 next = rrset->next;
267 mDNSPlatformMemFree(rrset);
268 rrset = next;
269 }
270 dv->key = mDNSNULL;
271
272 rrset = dv->rrsigKey;
273 while (rrset)
274 {
275 next = rrset->next;
276 mDNSPlatformMemFree(rrset);
277 rrset = next;
278 }
279 dv->rrsigKey = mDNSNULL;
280
281 rrset = dv->ds;
282 while (rrset)
283 {
284 next = rrset->next;
285 mDNSPlatformMemFree(rrset);
286 rrset = next;
287 }
288 dv->ds = mDNSNULL;
289 if (dv->pendingNSEC)
290 {
291 mDNSPlatformMemFree(dv->pendingNSEC);
292 dv->pendingNSEC = mDNSNULL;
293 }
294 }
295
296 mDNSexport void FreeDNSSECVerifier(mDNS *const m, DNSSECVerifier *dv)
297 {
298 LogDNSSEC("FreeDNSSECVerifier called %p", dv);
299 if (dv->q.ThisQInterval != -1) mDNS_StopQuery(m, &dv->q);
300 FreeDNSSECVerifierRRSets(dv);
301 if (dv->ctx) AlgDestroy(dv->ctx);
302 if (dv->ac) FreeDNSSECAuthChain(dv);
303 if (dv->parent)
304 {
305 LogDNSSEC("FreeDNSSECVerifier freeing parent %p", dv->parent);
306 FreeDNSSECVerifier(m, dv->parent);
307 }
308 mDNSPlatformMemFree(dv);
309 }
310
311 mDNSexport RRVerifier* AllocateRRVerifier(const ResourceRecord *const rr, mStatus *status)
312 {
313 RRVerifier *r;
314
315 r = mDNSPlatformMemAllocate(sizeof (RRVerifier) + rr->rdlength);
316 if (!r)
317 {
318 LogMsg("AllocateRRVerifier: memory failure");
319 *status = mStatus_NoMemoryErr;
320 return mDNSNULL;
321 }
322 r->next = mDNSNULL;
323 r->rrtype = rr->rrtype;
324 r->rrclass = rr->rrclass;
325 r->rroriginalttl = rr->rroriginalttl;
326 r->rdlength = rr->rdlength;
327 r->namehash = rr->namehash;
328 r->rdatahash = rr->rdatahash;
329 AssignDomainName(&r->name, rr->name);
330 r->rdata = (mDNSu8*) ((mDNSu8 *)r + sizeof(RRVerifier));
331
332 // When we parsed the DNS response in GeLargeResourceRecord, for some records, we parse them into
333 // host order so that the rest of the code does not have to bother with converting from network order
334 // to host order. For signature verification, we need them back in network order. For DNSSEC records
335 // like DNSKEY and DS, we just copy over the data both in GetLargeResourceRecord and putRData.
336
337 if (!putRData(mDNSNULL, r->rdata, r->rdata + rr->rdlength, rr))
338 {
339 LogMsg("AllocateRRVerifier: putRData failed");
340 *status = mStatus_BadParamErr;
341 return mDNSNULL;
342 }
343 *status = mStatus_NoError;
344 return r;
345 }
346
347 mDNSexport mStatus AddRRSetToVerifier(DNSSECVerifier *dv, const ResourceRecord *const rr, RRVerifier *rv, RRVerifierSet set)
348 {
349 RRVerifier *r;
350 RRVerifier **v;
351 mStatus status;
352
353 if (!rv)
354 {
355 r = AllocateRRVerifier(rr, &status);
356 if (!r) return status;
357 }
358 else
359 r = rv;
360
361 switch (set)
362 {
363 case RRVS_rr:
364 v = &dv->rrset;
365 break;
366 case RRVS_rrsig:
367 v = &dv->rrsig;
368 break;
369 case RRVS_key:
370 v = &dv->key;
371 break;
372 case RRVS_rrsig_key:
373 v = &dv->rrsigKey;
374 break;
375 case RRVS_ds:
376 v = &dv->ds;
377 break;
378 default:
379 LogMsg("AddRRSetToVerifier: ERROR!! default case %d", set);
380 return mStatus_BadParamErr;
381 }
382 while (*v)
383 v = &(*v)->next;
384 *v = r;
385 return mStatus_NoError;
386 }
387
388 // Validate the RRSIG. "type" tells which RRSIG that we are supposed to validate. We fetch RRSIG for
389 // the rrset (type is RRVS_rrsig) and RRSIG for the key (type is RRVS_rrsig_key).
390 mDNSexport void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const ResourceRecord *const rr)
391 {
392 RRVerifier *rv;
393 mDNSu32 currentTime;
394 rdataRRSig *rrsigRData = (rdataRRSig *)((mDNSu8 *)rr->rdata + sizeofRDataHeader);
395
396 if (type == RRVS_rrsig)
397 {
398 rv = dv->rrset;
399 }
400 else if (type == RRVS_rrsig_key)
401 {
402 rv = dv->key;
403 }
404 else
405 {
406 LogMsg("ValidateRRSIG: ERROR!! type not valid %d", type);
407 return;
408 }
409
410 // RFC 4035:
411 // For each authoritative RRset in a signed zone, there MUST be at least
412 // one RRSIG record that meets the following requirements:
413 //
414 // RRSet is defined by same name, class and type
415 //
416 // 1. The RRSIG RR and the RRset MUST have the same owner name and the same class.
417 if (!SameDomainName(&rv->name, rr->name) || (rr->rrclass != rv->rrclass))
418 {
419 debugdnssec("ValidateRRSIG: name mismatch or class mismatch");
420 return;
421 }
422
423 // 2. The RRSIG RR's Type Covered field MUST equal the RRset's type.
424 if ((swap16(rrsigRData->typeCovered)) != rv->rrtype)
425 {
426 debugdnssec("ValidateRRSIG: typeCovered mismatch rrsig %d, rr type %d", swap16(rrsigRData->typeCovered), rv->rrtype);
427 return;
428 }
429
430 // 3. The number of labels in the RRset owner name MUST be greater than or equal
431 // to the value in the RRSIG RR's Labels field.
432 if (rrsigRData->labels > CountLabels(&rv->name))
433 {
434 debugdnssec("ValidateRRSIG: labels count problem rrsig %d, rr %d", rrsigRData->labels, CountLabels(&rv->name));
435 return;
436 }
437
438 // 4. The RRSIG RR's Signer's Name field MUST be the name of the zone that contains
439 // the RRset. For a stub resolver, this can't be done in a secure way. Hence we
440 // do it this way (discussed in dnsext mailing list)
441 switch (rv->rrtype)
442 {
443 case kDNSType_NS:
444 case kDNSType_SOA:
445 case kDNSType_DNSKEY:
446 //Signed by the owner
447 if (!SameDomainName(&rv->name, (domainname *)&rrsigRData->signerName))
448 {
449 debugdnssec("ValidateRRSIG: Signer Name does not match the record name for %s", DNSTypeName(rv->rrtype));
450 return;
451 }
452 break;
453 case kDNSType_DS:
454 // Should be signed by the parent
455 if (SameDomainName(&rv->name, (domainname *)&rrsigRData->signerName))
456 {
457 debugdnssec("ValidateRRSIG: Signer Name matches the record name for %s", DNSTypeName(rv->rrtype));
458 return;
459 }
460 // FALLTHROUGH
461 default:
462 {
463 int c1 = CountLabels(&rv->name);
464 int c2 = CountLabels((domainname *)&rrsigRData->signerName);
465 if (c1 < c2)
466 {
467 debugdnssec("ValidateRRSIG: Signer Name not a subdomain label count %d < %d ", c1, c2);
468 return;
469 }
470 domainname *d = (domainname *)SkipLeadingLabels(&rv->name, c1 - c2);
471 if (!SameDomainName(d, (domainname *)&rrsigRData->signerName))
472 {
473 debugdnssec("ValidateRRSIG: Signer Name not a subdomain");
474 return;
475 }
476 break;
477 }
478 }
479
480 // 5. The validator's notion of the current time MUST be less than or equal to the
481 // time listed in the RRSIG RR's Expiration field.
482 //
483 // 6. The validator's notion of the current time MUST be greater than or equal to the
484 // time listed in the RRSIG RR's Inception field.
485 currentTime = mDNSPlatformUTC();
486
487 if (DNS_SERIAL_LT(swap32(rrsigRData->sigExpireTime), currentTime))
488 {
489 LogDNSSEC("ValidateRRSIG: Expired: currentTime %d, ExpireTime %d", (int)currentTime,
490 swap32((int)rrsigRData->sigExpireTime));
491 return;
492 }
493 if (DNS_SERIAL_LT(currentTime, swap32(rrsigRData->sigInceptTime)))
494 {
495 LogDNSSEC("ValidateRRSIG: Future: currentTime %d, InceptTime %d", (int)currentTime,
496 swap32((int)rrsigRData->sigInceptTime));
497 return;
498 }
499
500 if (AddRRSetToVerifier(dv, rr, mDNSNULL, type) != mStatus_NoError)
501 {
502 LogMsg("ValidateRRSIG: ERROR!! cannot allocate RRSet");
503 return;
504 }
505 }
506
507 mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
508 {
509 mDNSu32 slot;
510 CacheGroup *cg;
511 CacheRecord *cr;
512 RRVerifier *rv;
513
514 *negcr = mDNSNULL;
515 if (!dv->rrset)
516 {
517 LogMsg("CheckRRSIGForRRSet: ERROR!! rrset NULL for origName %##s (%s)", dv->origName.c,
518 DNSTypeName(dv->origType));
519 return mStatus_BadParamErr;
520 }
521
522 rv = dv->rrset;
523 slot = HashSlot(&rv->name);
524 cg = CacheGroupForName(m, slot, rv->namehash, &rv->name);
525 if (!cg)
526 {
527 debugdnssec("CheckRRSIGForRRSet: cg null");
528 return mStatus_NoSuchRecord;
529 }
530
531 for (cr=cg->members; cr; cr=cr->next)
532 {
533 debugdnssec("CheckRRSIGForRRSet: checking the validity of rrsig");
534 if (cr->resrec.rrtype != kDNSType_RRSIG) continue;
535 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
536 {
537 if (!(*negcr))
538 {
539 LogDNSSEC("CheckRRSIGForRRSet: Negative cache record %s encountered for %##s (%s)", CRDisplayString(m, cr),
540 rv->name.c, rv->rrtype);
541 *negcr = cr;
542 }
543 else
544 {
545 LogMsg("CheckRRSIGForRRSet: ERROR!! Negative cache record %s already set for %##s (%s)", CRDisplayString(m, cr),
546 rv->name.c, rv->rrtype);
547 }
548 continue;
549 }
550 ValidateRRSIG(dv, RRVS_rrsig, &cr->resrec);
551 }
552 if (*negcr && dv->rrsig)
553 {
554 // Encountered both RRSIG and negative CR
555 LogMsg("CheckRRSIGForRRSet: ERROR!! Encountered negative cache record %s and RRSIG for %##s (%s)",
556 CRDisplayString(m, *negcr), rv->name.c, rv->rrtype);
557 return mStatus_BadParamErr;
558 }
559 if (dv->rrsig || *negcr)
560 return mStatus_NoError;
561 else
562 return mStatus_NoSuchRecord;
563 }
564
565 mDNSlocal void CheckOneKeyForRRSIG(DNSSECVerifier *dv, const ResourceRecord *const rr)
566 {
567 rdataRRSig *rrsig;
568
569 if (!dv->rrsig)
570 {
571 LogMsg("CheckOneKeyForRRSIG: ERROR!! rrsig NULL");
572 return;
573 }
574 rrsig = (rdataRRSig *)dv->rrsig->rdata;
575 if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
576 {
577 debugdnssec("CheckOneKeyForRRSIG: name mismatch");
578 return;
579 }
580
581 // We store all the keys including the ZSK and KSK and use them appropriately
582 // later
583 if (AddRRSetToVerifier(dv, rr, mDNSNULL, RRVS_key) != mStatus_NoError)
584 {
585 LogMsg("CheckOneKeyForRRSIG: ERROR!! cannot allocate RRSet");
586 return;
587 }
588 }
589
590 mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
591 {
592 mDNSu32 slot;
593 mDNSu32 namehash;
594 CacheGroup *cg;
595 CacheRecord *cr;
596 rdataRRSig *rrsig;
597 domainname *name;
598
599 *negcr = mDNSNULL;
600 if (!dv->rrsig)
601 {
602 LogMsg("CheckKeyForRRSIG: ERROR!! rrsig NULL");
603 return mStatus_BadParamErr;
604 }
605
606 // Signer name should be the same on all rrsig ??
607 rrsig = (rdataRRSig *)dv->rrsig->rdata;
608 name = (domainname *)&rrsig->signerName;
609
610 slot = HashSlot(name);
611 namehash = DomainNameHashValue(name);
612 cg = CacheGroupForName(m, slot, namehash, name);
613 if (!cg)
614 {
615 debugdnssec("CheckKeyForRRSIG: cg null for %##s", name->c);
616 return mStatus_NoSuchRecord;
617 }
618
619 for (cr=cg->members; cr; cr=cr->next)
620 {
621 if (cr->resrec.rrtype != kDNSType_DNSKEY) continue;
622 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
623 {
624 if (!(*negcr))
625 {
626 LogDNSSEC("CheckKeyForRRSIG: Negative cache record %s encountered for %##s (DNSKEY)", CRDisplayString(m, cr),
627 name->c);
628 *negcr = cr;
629 }
630 else
631 {
632 LogMsg("CheckKeyForRRSIG: ERROR!! Negative cache record %s already set for %##s (DNSKEY)", CRDisplayString(m, cr),
633 name->c);
634 }
635 continue;
636 }
637 debugdnssec("CheckKeyForRRSIG: checking the validity of key record");
638 CheckOneKeyForRRSIG(dv, &cr->resrec);
639 }
640 if (*negcr && dv->key)
641 {
642 // Encountered both RRSIG and negative CR
643 LogMsg("CheckKeyForRRSIG: ERROR!! Encountered negative cache record %s and DNSKEY for %##s",
644 CRDisplayString(m, *negcr), name->c);
645 return mStatus_BadParamErr;
646 }
647 if (dv->key || *negcr)
648 return mStatus_NoError;
649 else
650 return mStatus_NoSuchRecord;
651 }
652
653 mDNSlocal void CheckOneRRSIGForKey(DNSSECVerifier *dv, const ResourceRecord *const rr)
654 {
655 rdataRRSig *rrsig;
656 if (!dv->rrsig)
657 {
658 LogMsg("CheckOneRRSIGForKey: ERROR!! rrsig NULL");
659 return;
660 }
661 rrsig = (rdataRRSig *)dv->rrsig->rdata;
662 if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
663 {
664 debugdnssec("CheckOneRRSIGForKey: name mismatch");
665 return;
666 }
667 ValidateRRSIG(dv, RRVS_rrsig_key, rr);
668 }
669
670 mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
671 {
672 mDNSu32 slot;
673 mDNSu32 namehash;
674 CacheGroup *cg;
675 CacheRecord *cr;
676 rdataRRSig *rrsig;
677 domainname *name;
678
679 *negcr = mDNSNULL;
680 if (!dv->rrsig)
681 {
682 LogMsg("CheckRRSIGForKey: ERROR!! rrsig NULL");
683 return mStatus_BadParamErr;
684 }
685 if (!dv->key)
686 {
687 LogMsg("CheckRRSIGForKey: ERROR!! key NULL");
688 return mStatus_BadParamErr;
689 }
690 rrsig = (rdataRRSig *)dv->rrsig->rdata;
691 name = (domainname *)&rrsig->signerName;
692
693 slot = HashSlot(name);
694 namehash = DomainNameHashValue(name);
695 cg = CacheGroupForName(m, slot, namehash, name);
696 if (!cg)
697 {
698 debugdnssec("CheckRRSIGForKey: cg null %##s", name->c);
699 return mStatus_NoSuchRecord;
700 }
701 for (cr=cg->members; cr; cr=cr->next)
702 {
703 if (cr->resrec.rrtype != kDNSType_RRSIG) continue;
704 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
705 {
706 if (!(*negcr))
707 {
708 LogDNSSEC("CheckRRSIGForKey: Negative cache record %s encountered for %##s (RRSIG)", CRDisplayString(m, cr),
709 name->c);
710 *negcr = cr;
711 }
712 else
713 {
714 LogMsg("CheckRRSIGForKey: ERROR!! Negative cache record %s already set for %##s (RRSIG)", CRDisplayString(m, cr),
715 name->c);
716 }
717 continue;
718 }
719 debugdnssec("CheckRRSIGForKey: checking the validity of rrsig");
720 CheckOneRRSIGForKey(dv, &cr->resrec);
721 }
722 if (*negcr && dv->rrsigKey)
723 {
724 // Encountered both RRSIG and negative CR
725 LogMsg("CheckRRSIGForKey: ERROR!! Encountered negative cache record %s and DNSKEY for %##s",
726 CRDisplayString(m, *negcr), name->c);
727 return mStatus_BadParamErr;
728 }
729 if (dv->rrsigKey || *negcr)
730 return mStatus_NoError;
731 else
732 return mStatus_NoSuchRecord;
733 }
734
735 mDNSlocal void CheckOneDSForKey(DNSSECVerifier *dv, const ResourceRecord *const rr)
736 {
737 mDNSu16 tag;
738 rdataDS *DS;
739 RRVerifier *keyv;
740 rdataDNSKey *key;
741 rdataRRSig *rrsig;
742
743 if (!dv->rrsig)
744 {
745 LogMsg("CheckOneDSForKey: ERROR!! rrsig NULL");
746 return;
747 }
748 rrsig = (rdataRRSig *)dv->rrsig->rdata;
749 DS = (rdataDS *)((mDNSu8 *)rr->rdata + sizeofRDataHeader);
750
751 if (!SameDomainName((domainname *)&rrsig->signerName, rr->name))
752 {
753 debugdnssec("CheckOneDSForKey: name mismatch");
754 return;
755 }
756 for (keyv = dv->key; keyv; keyv = keyv->next)
757 {
758 key = (rdataDNSKey *)keyv->rdata;
759 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
760 if (tag != swap16(DS->keyTag))
761 {
762 debugdnssec("CheckOneDSForKey: keyTag mismatch keyTag %d, DStag %d", tag, swap16(DS->keyTag));
763 continue;
764 }
765 if (key->alg != DS->alg)
766 {
767 debugdnssec("CheckOneDSForKey: alg mismatch key alg%d, DS alg %d", key->alg, swap16(DS->alg));
768 continue;
769 }
770 if (AddRRSetToVerifier(dv, rr, mDNSNULL, RRVS_ds) != mStatus_NoError)
771 {
772 debugdnssec("CheckOneDSForKey: cannot allocate RRSet");
773 }
774 }
775 }
776
777 mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
778 {
779 mDNSu32 slot;
780 mDNSu32 namehash;
781 CacheGroup *cg;
782 CacheRecord *cr;
783 rdataRRSig *rrsig;
784 domainname *name;
785
786 *negcr = mDNSNULL;
787 if (!dv->rrsig)
788 {
789 LogMsg("CheckDSForKey: ERROR!! rrsig NULL");
790 return mStatus_BadParamErr;
791 }
792 if (!dv->key)
793 {
794 LogMsg("CheckDSForKey: ERROR!! key NULL");
795 return mStatus_BadParamErr;
796 }
797 rrsig = (rdataRRSig *)dv->rrsig->rdata;
798 name = (domainname *)&rrsig->signerName;
799 slot = HashSlot(name);
800 namehash = DomainNameHashValue(name);
801 cg = CacheGroupForName(m, slot, namehash, name);
802 if (!cg)
803 {
804 debugdnssec("CheckDSForKey: cg null for %s", name->c);
805 return mStatus_NoSuchRecord;
806 }
807 for (cr=cg->members; cr; cr=cr->next)
808 {
809 if (cr->resrec.rrtype != kDNSType_DS) continue;
810 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
811 {
812 if (!(*negcr))
813 {
814 LogDNSSEC("CheckDSForKey: Negative cache record %s encountered for %##s (DS)", CRDisplayString(m, cr),
815 name->c);
816 *negcr = cr;
817 }
818 else
819 {
820 LogMsg("CheckDSForKey: ERROR!! Negative cache record %s already set for %##s (DS)", CRDisplayString(m, cr),
821 name->c);
822 }
823 continue;
824 }
825 CheckOneDSForKey(dv, &cr->resrec);
826 }
827 if (*negcr && dv->ds)
828 {
829 // Encountered both RRSIG and negative CR
830 LogMsg("CheckDSForKey: ERROR!! Encountered negative cache record %s and DS for %##s",
831 CRDisplayString(m, *negcr), name->c);
832 return mStatus_BadParamErr;
833 }
834 if (dv->ds || *negcr)
835 return mStatus_NoError;
836 else
837 return mStatus_NoSuchRecord;
838 return (dv->ds ? mStatus_NoError : mStatus_NoSuchRecord);
839 }
840
841 // It returns mDNStrue if we have all the rrsets for verification and mDNSfalse otherwise.
842 mDNSlocal mDNSBool GetAllRRSetsForVerification(mDNS *const m, DNSSECVerifier *dv)
843 {
844 mStatus err;
845 CacheRecord *negcr;
846 rdataRRSig *rrsig;
847
848 if (!dv->rrset)
849 {
850 LogMsg("GetAllRRSetsForVerification: ERROR!! rrset NULL");
851 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
852 return mDNSfalse;
853 }
854
855 if (dv->next == RRVS_done) return mDNStrue;
856
857 debugdnssec("GetAllRRSetsForVerification: next %d", dv->next);
858 switch (dv->next)
859 {
860 case RRVS_rrsig:
861 // If we can't find the RRSIG for the rrset, re-issue the query.
862 //
863 // NOTE: It is possible that the cache might answer partially e.g., RRSIGs match qtype but the
864 // whole set is not there. In that case the validation will fail. Ideally we should flush the
865 // cache and reissue the query (TBD).
866 err = CheckRRSIGForRRSet(m, dv, &negcr);
867 if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
868 {
869 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
870 return mDNSfalse;
871 }
872 // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
873 // looks in "dv->q" for the proof. Note that we have to use currQtype as the response could be
874 // a CNAME and dv->rrset->rrtype would be set to CNAME and not the original question type that
875 // resulted in CNAME.
876 InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->rrset->name, dv->currQtype, VerifySigCallback, dv);
877 // We may not have the NSECS if the previous query was a non-DNSSEC query
878 if (negcr && negcr->nsec)
879 {
880 dv->DVCallback = DNSSECNegativeValidationCB;
881 ValidateWithNSECS(m, dv, negcr);
882 return mDNSfalse;
883 }
884
885 dv->next = RRVS_key;
886 if (!dv->rrsig)
887 {
888 // We already found the rrset to verify. Ideally we should just issue the query for the RRSIG. Unfortunately,
889 // that does not work well as the response may not contain the RRSIG whose typeCovered matches the
890 // rrset->rrtype (recursive server returns what is in its cache). Hence, we send the original query with the
891 // DO bit set again to get the RRSIG. Normally this would happen if there was question which did not require
892 // DNSSEC validation (ValidationRequied = 0) populated the cache and later when the ValidationRequired question
893 // comes along, we need to get the RRSIGs. If we started off with ValidationRequired question we would have
894 // already set the DO bit and not able to get RRSIGs e.g., bad CPE device, we would reissue the query here
895 // again once more.
896 //
897 // Also, if it is a wildcard expanded answer, we need to issue the query with the original type for it to
898 // elicit the right NSEC records. Just querying for RRSIG alone is not sufficient.
899 //
900 // Note: For this to work, the core needs to deliver RRSIGs when they are added to the cache even if the
901 // "qtype" is not RRSIG.
902 debugdnssec("GetAllRRSetsForVerification: Fetching RRSIGS for RRSET");
903 mDNS_StartQuery(m, &dv->q);
904 return mDNSfalse;
905 }
906 // if we found the RRSIG, then fall through to find the DNSKEY
907 case RRVS_key:
908 err = CheckKeyForRRSIG(m, dv, &negcr);
909 if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
910 {
911 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
912 return mDNSfalse;
913 }
914 // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
915 // looks in "dv->q" for the proof.
916 rrsig = (rdataRRSig *)dv->rrsig->rdata;
917 InitializeQuestion(m, &dv->q, dv->InterfaceID, (domainname *)&rrsig->signerName, kDNSType_DNSKEY, VerifySigCallback, dv);
918 // We may not have the NSECS if the previous query was a non-DNSSEC query
919 if (negcr && negcr->nsec)
920 {
921 dv->DVCallback = DNSSECNegativeValidationCB;
922 ValidateWithNSECS(m, dv, negcr);
923 return mDNSfalse;
924 }
925
926 dv->next = RRVS_rrsig_key;
927 if (!dv->key)
928 {
929 debugdnssec("GetAllRRSetsForVerification: Fetching DNSKEY for RRSET");
930 mDNS_StartQuery(m, &dv->q);
931 return mDNSfalse;
932 }
933 // if we found the DNSKEY, then fall through to find the RRSIG for the DNSKEY
934 case RRVS_rrsig_key:
935 err = CheckRRSIGForKey(m, dv, &negcr);
936 // if we are falling through, then it is okay if we don't find the record
937 if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
938 {
939 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
940 return mDNSfalse;
941 }
942 // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
943 // looks in "dv->q" for the proof.
944 rrsig = (rdataRRSig *)dv->rrsig->rdata;
945 InitializeQuestion(m, &dv->q, dv->InterfaceID, (domainname *)&rrsig->signerName, kDNSType_DNSKEY, VerifySigCallback, dv);
946 // We may not have the NSECS if the previous query was a non-DNSSEC query
947 if (negcr && negcr->nsec)
948 {
949 dv->DVCallback = DNSSECNegativeValidationCB;
950 ValidateWithNSECS(m, dv, negcr);
951 return mDNSfalse;
952 }
953 dv->next = RRVS_ds;
954 debugdnssec("VerifySigCallback: RRVS_rrsig_key %p", dv->rrsigKey);
955 if (!dv->rrsigKey)
956 {
957 debugdnssec("GetAllRRSetsForVerification: Fetching RRSIGS for DNSKEY");
958 mDNS_StartQuery(m, &dv->q);
959 return mDNSfalse;
960 }
961 // if we found RRSIG for the DNSKEY, then fall through to find the DS
962 case RRVS_ds:
963 {
964 domainname *qname;
965 rrsig = (rdataRRSig *)dv->rrsig->rdata;
966 qname = (domainname *)&rrsig->signerName;
967
968 err = CheckDSForKey(m, dv, &negcr);
969 if (err != mStatus_NoSuchRecord && err != mStatus_NoError)
970 {
971 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
972 return mDNSfalse;
973 }
974 // Need to initialize the question as if we end up in ValidateWithNSECS below, the nsec proofs
975 // looks in "dv->q" for the proof.
976 InitializeQuestion(m, &dv->q, dv->InterfaceID, qname, kDNSType_DS, VerifySigCallback, dv);
977 // We may not have the NSECS if the previous query was a non-DNSSEC query
978 if (negcr && negcr->nsec)
979 {
980 dv->DVCallback = DNSSECNegativeValidationCB;
981 ValidateWithNSECS(m, dv, negcr);
982 return mDNSfalse;
983 }
984 dv->next = RRVS_done;
985 // If we have a trust anchor, then don't bother looking up the DS record
986 if (!dv->ds && !TrustedKeyPresent(m, dv))
987 {
988 // There is no DS for the root. Hence, if we don't have the trust
989 // anchor for root, just fail.
990 if (SameDomainName(qname, (const domainname *)"\000"))
991 {
992 LogDNSSEC("GetAllRRSetsForVerification: Reached root");
993 dv->DVCallback(m, dv, DNSSEC_Bogus);
994 return mDNSfalse;
995 }
996 debugdnssec("GetAllRRSetsForVerification: Fetching DS");
997 mDNS_StartQuery(m, &dv->q);
998 return mDNSfalse;
999 }
1000 else
1001 {
1002 debugdnssec("GetAllRRSetsForVerification: Skipped fetching the DS");
1003 return mDNStrue;
1004 }
1005 }
1006 default:
1007 LogMsg("GetAllRRSetsForVerification: ERROR!! unknown next %d", dv->next);
1008 dv->DVCallback(m, dv, DNSSEC_Bogus);
1009 return mDNSfalse;
1010 }
1011 }
1012
1013 #ifdef DNSSEC_DEBUG
1014 mDNSlocal void PrintFixedSignInfo(rdataRRSig *rrsig, domainname *signerName, int sigNameLen, mDNSu8 *fixedPart, int fixedPartLen)
1015 {
1016 int j;
1017 char buf[RRSIG_FIXED_SIZE *3 + 1]; // 3 bytes count for %2x + 1 and the one byte for null at the end
1018 char sig[sigNameLen * 3 + 1];
1019 char fp[fixedPartLen * 3 + 1];
1020 int length;
1021
1022 length = 0;
1023 for (j = 0; j < RRSIG_FIXED_SIZE; j++)
1024 length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", ((mDNSu8 *)rrsig)[j]);
1025 LogMsg("RRSIG(%d) %s", RRSIG_FIXED_SIZE, buf);
1026
1027
1028 length = 0;
1029 for (j = 0; j < sigNameLen; j++)
1030 length += mDNS_snprintf(sig+length, sizeof(sig) - length - 1, "%2x ", signerName->c[j]);
1031 LogMsg("SIGNAME(%d) %s", sigNameLen, sig);
1032
1033 length = 0;
1034 for (j = 0; j < fixedPartLen; j++)
1035 length += mDNS_snprintf(fp+length, sizeof(fp) - length - 1, "%2x ", fixedPart[j]);
1036 LogMsg("fixedPart(%d) %s", fixedPartLen, fp);
1037 }
1038
1039 mDNSlocal void PrintVarSignInfo(mDNSu16 rdlen, mDNSu8 *rdata)
1040 {
1041 unsigned int j;
1042 mDNSu8 *r;
1043 unsigned int blen = swap16(rdlen);
1044 char buf[blen * 3 + 1]; // 3 bytes count for %2x + 1 and the one byte for null at the end
1045 int length;
1046
1047 length = 0;
1048
1049 r = (mDNSu8 *)&rdlen;
1050 for (j = 0; j < sizeof(mDNSu16); j++)
1051 length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", r[j]);
1052 LogMsg("RDLENGTH(%d) %s", sizeof(mDNSu16), buf);
1053
1054 length = 0;
1055 for (j = 0; j < blen; j++)
1056 length += mDNS_snprintf(buf+length, sizeof(buf) - length - 1, "%2x ", rdata[j]);
1057 LogMsg("RDATA(%d) %s", blen, buf);
1058 }
1059 #else
1060 mDNSlocal void PrintVarSignInfo(mDNSu16 rdlen, mDNSu8 *rdata)
1061 {
1062 (void)rdlen;
1063 (void)rdata;
1064 }
1065 mDNSlocal void PrintFixedSignInfo(rdataRRSig *rrsig, domainname *signerName, int sigNameLen, mDNSu8 *fixedPart, int fixedPartLen)
1066 {
1067 (void)rrsig;
1068 (void)signerName;
1069 (void)sigNameLen;
1070 (void)fixedPart;
1071 (void)fixedPartLen;
1072 }
1073 #endif
1074
1075 // Used for RDATA comparison
1076 typedef struct
1077 {
1078 mDNSu16 rdlength;
1079 mDNSu16 rrtype;
1080 mDNSu8 *rdata;
1081 } rdataComp;
1082
1083 mDNSlocal int rdata_compare(mDNSu8 *const rdata1, mDNSu8 *const rdata2, int rdlen1, int rdlen2)
1084 {
1085 int len;
1086 int ret;
1087
1088 len = (rdlen1 < rdlen2) ? rdlen1 : rdlen2;
1089
1090 ret = DNSMemCmp(rdata1, rdata2, len);
1091 if (ret != 0) return ret;
1092
1093 // RDATA is same at this stage. Consider them equal if they are of same length. Otherwise
1094 // decide based on their lengths.
1095 return ((rdlen1 == rdlen2) ? 0 : (rdlen1 < rdlen2) ? -1 : 1);
1096 }
1097
1098 mDNSlocal int name_compare(mDNSu8 *const rdata1, mDNSu8 *const rdata2, int rdlen1, int rdlen2)
1099 {
1100 domainname *n1 = (domainname *)rdata1;
1101 domainname *n2 = (domainname *)rdata2;
1102 mDNSu8 *a = n1->c;
1103 mDNSu8 *b = n2->c;
1104 int count, c1, c2;
1105 int i, j, len;
1106
1107 c1 = CountLabels(n1);
1108 c2 = CountLabels(n2);
1109
1110 count = c1 < c2 ? c1 : c2;
1111
1112 // We can't use SameDomainName as we need to know exactly which is greater/smaller
1113 // for sorting purposes. Hence, we need to compare label by label
1114 for (i = 0; i < count; i++)
1115 {
1116 // Are the lengths same ?
1117 if (*a != *b)
1118 {
1119 debugdnssec("compare_name: returning c1 %d, c2 %d", *a, *b);
1120 return ((*a < *b) ? -1 : 1);
1121 }
1122 len = *a;
1123 rdlen1 -= (len + 1);
1124 rdlen2 -= (len + 1);
1125 if (rdlen1 < 0 || rdlen2 < 0)
1126 {
1127 LogMsg("name_compare: ERROR!! not enough data rdlen1 %d, rdlen2 %d", rdlen1, rdlen2);
1128 return -1;
1129 }
1130 a++; b++;
1131 for (j = 0; j < len; j++)
1132 {
1133 mDNSu8 ac = *a++;
1134 mDNSu8 bc = *b++;
1135 if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
1136 if (mDNSIsUpperCase(bc)) bc += 'a' - 'A';
1137 if (ac != bc)
1138 {
1139 debugdnssec("compare_name: returning ac %c, bc %c", ac, bc);
1140 return ((ac < bc) ? -1 : 1);
1141 }
1142 }
1143 }
1144
1145 return 0;
1146 }
1147
1148 mDNSlocal int srv_compare(rdataComp *const r1, rdataComp *const r2)
1149 {
1150 int res;
1151 int length1, length2;
1152
1153 length1 = r1->rdlength;
1154 length2 = r2->rdlength;
1155 // We should have at least priority, weight, port plus 1 byte
1156 if (length1 < 7 || length2 < 7)
1157 {
1158 LogMsg("srv_compare: ERROR!! Length smaller than 7 bytes");
1159 return -1;
1160 }
1161 // Compare priority, weight and port
1162 res = DNSMemCmp(r1->rdata, r2->rdata, 6);
1163 if (res != 0) return res;
1164 length1 -= 6;
1165 length2 -= 6;
1166 return (name_compare(r1->rdata + 6, r2->rdata + 6, length1, length2));
1167 }
1168
1169 mDNSlocal int tsig_compare(rdataComp *const r1, rdataComp *const r2)
1170 {
1171 int offset1, offset2;
1172 int length1, length2;
1173 int res, dlen;
1174
1175 offset1 = offset2 = 0;
1176 length1 = r1->rdlength;
1177 length2 = r2->rdlength;
1178
1179 // we should have at least one byte to start with
1180 if (length1 < 1 || length2 < 1)
1181 {
1182 LogMsg("sig_compare: Length smaller than 18 bytes");
1183 return -1;
1184 }
1185
1186 res = name_compare(r1->rdata, r2->rdata, length1, length2);
1187 if (res != 0) return res;
1188
1189 dlen = DomainNameLength((domainname *)r1->rdata);
1190 offset1 += dlen;
1191 offset2 += dlen;
1192 length1 -= dlen;
1193 length2 -= dlen;
1194
1195 if (length1 <= 1 || length2 <= 1)
1196 {
1197 LogMsg("tsig_compare: data too small to compare length1 %d, length2 %d", length1, length2);
1198 return -1;
1199 }
1200
1201 return (rdata_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2));
1202 }
1203
1204 // Compares types that conform to : <length><Value>
1205 mDNSlocal int lenval_compare(mDNSu8 *d1, mDNSu8 *d2, int *len1, int *len2, int rem1, int rem2)
1206 {
1207 int len;
1208 int res;
1209
1210 if (rem1 <= 1 || rem2 <= 1)
1211 {
1212 LogMsg("lenval_compare: data too small to compare length1 %d, length2 %d", rem1, rem2);
1213 return -1;
1214 }
1215 *len1 = (int)d1[0];
1216 *len2 = (int)d2[0];
1217 len = (*len1 < *len2 ? *len1 : *len2);
1218 res = DNSMemCmp(d1, d2, len + 1);
1219 return res;
1220 }
1221
1222 // RFC 2915: Order (2) Preference(2) and variable length: Flags Service Regexp Replacement
1223 mDNSlocal int naptr_compare(rdataComp *const r1, rdataComp *const r2)
1224 {
1225 mDNSu8 *d1 = r1->rdata;
1226 mDNSu8 *d2 = r2->rdata;
1227 int len1, len2, res;
1228 int length1, length2;
1229
1230 length1 = r1->rdlength;
1231 length2 = r2->rdlength;
1232
1233 // Order, Preference plus at least 1 byte
1234 if (length1 < 5 || length2 < 5)
1235 {
1236 LogMsg("naptr_compare: Length smaller than 18 bytes");
1237 return -1;
1238 }
1239 // Compare order and preference
1240 res = DNSMemCmp(d1, d2, 4);
1241 if (res != 0) return res;
1242
1243 d1 += 4;
1244 d2 += 4;
1245 length1 -= 4;
1246 length2 -= 4;
1247
1248 // Compare Flags (including the length byte)
1249 res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1250 if (res != 0) return res;
1251 d1 += (len1 + 1);
1252 d2 += (len2 + 1);
1253 length1 -= (len1 + 1);
1254 length2 -= (len2 + 1);
1255
1256 // Compare Service (including the length byte)
1257 res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1258 if (res != 0) return res;
1259 d1 += (len1 + 1);
1260 d2 += (len2 + 1);
1261 length1 -= (len1 + 1);
1262 length2 -= (len2 + 1);
1263
1264 // Compare regexp (including the length byte)
1265 res = lenval_compare(d1, d2, &len1, &len2, length1, length2);
1266 if (res != 0) return res;
1267 d1 += (len1 + 1);
1268 d2 += (len2 + 1);
1269 length1 -= (len1 + 1);
1270 length2 -= (len2 + 1);
1271
1272 // Compare Replacement
1273 return name_compare(d1, d2, length1, length2);
1274 }
1275
1276 // RFC 1035: MINFO: Two domain names
1277 // RFC 1183: RP: Two domain names
1278 mDNSlocal int dom2_compare(mDNSu8 *d1, mDNSu8 *d2, int length1, int length2)
1279 {
1280 int res, dlen;
1281
1282 // We need at least one byte to start with
1283 if (length1 < 1 || length2 < 1)
1284 {
1285 LogMsg("dom2_compare:1: data too small length1 %d, length2 %d", length1, length2);
1286 return -1;
1287 }
1288 res = name_compare(d1, d2, length1, length2);
1289 if (res != 0) return res;
1290 dlen = DomainNameLength((domainname *)d1);
1291
1292 length1 -= dlen;
1293 length2 -= dlen;
1294 // We need at least one byte to start with
1295 if (length1 < 1 || length2 < 1)
1296 {
1297 LogMsg("dom2_compare:2: data too small length1 %d, length2 %d", length1, length2);
1298 return -1;
1299 }
1300
1301 d1 += dlen;
1302 d2 += dlen;
1303
1304 return name_compare(d1, d2, length1, length2);
1305 }
1306
1307 // MX : preference (2 bytes), domainname
1308 mDNSlocal int mx_compare(rdataComp *const r1, rdataComp *const r2)
1309 {
1310 int res;
1311 int length1, length2;
1312
1313 length1 = r1->rdlength;
1314 length2 = r2->rdlength;
1315
1316 // We need at least two bytes + 1 extra byte for the domainname to start with
1317 if (length1 < 3 || length2 < 3)
1318 {
1319 LogMsg("mx_compare: data too small length1 %d, length2 %d", length1, length2);
1320 return -1;
1321 }
1322
1323 res = DNSMemCmp(r1->rdata, r2->rdata, 2);
1324 if (res != 0) return res;
1325 length1 -= 2;
1326 length2 -= 2;
1327 return name_compare(r1->rdata + 2, r2->rdata + 2, length1, length2);
1328 }
1329
1330 // RFC 2163 (PX) : preference (2 bytes), map822. mapx400 (domainnames)
1331 mDNSlocal int px_compare(rdataComp *const r1, rdataComp *const r2)
1332 {
1333 int res;
1334
1335 // We need at least two bytes + 1 extra byte for the domainname to start with
1336 if (r1->rdlength < 3 || r2->rdlength < 3)
1337 {
1338 LogMsg("px_compare: data too small length1 %d, length2 %d", r1->rdlength, r2->rdlength);
1339 return -1;
1340 }
1341
1342 res = DNSMemCmp(r1->rdata, r2->rdata, 2);
1343 if (res != 0) return res;
1344
1345 return dom2_compare(r1->rdata + 2, r2->rdata + 2, r1->rdlength - 2, r2->rdlength - 2);
1346 }
1347
1348 mDNSlocal int soa_compare(rdataComp *r1, rdataComp *r2)
1349 {
1350 int res, dlen;
1351 int offset1, offset2;
1352 int length1, length2;
1353
1354 length1 = r1->rdlength;
1355 length2 = r2->rdlength;
1356 offset1 = offset2 = 0;
1357
1358 // We need at least 20 bytes plus 1 byte for each domainname
1359 if (length1 < 22 || length2 < 22)
1360 {
1361 LogMsg("soa_compare:1: data too small length1 %d, length2 %d", length1, length2);
1362 return -1;
1363 }
1364
1365 // There are two domainnames followed by 20 bytes of serial, refresh, retry, expire and min
1366 // Compare the names and then the rest of the bytes
1367
1368 res = name_compare(r1->rdata, r2->rdata, length1, length2);
1369 if (res != 0) return res;
1370
1371 dlen = DomainNameLength((domainname *)r1->rdata);
1372
1373 length1 -= dlen;
1374 length2 -= dlen;
1375 if (length1 < 1 || length2 < 1)
1376 {
1377 LogMsg("soa_compare:2: data too small length1 %d, length2 %d", length1, length2);
1378 return -1;
1379 }
1380 offset1 += dlen;
1381 offset2 += dlen;
1382
1383 res = name_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2);
1384 if (res != 0) return res;
1385
1386 dlen = DomainNameLength((domainname *)r1->rdata);
1387 length1 -= dlen;
1388 length2 -= dlen;
1389 if (length1 < 20 || length2 < 20)
1390 {
1391 LogMsg("soa_compare:3: data too small length1 %d, length2 %d", length1, length2);
1392 return -1;
1393 }
1394 offset1 += dlen;
1395 offset2 += dlen;
1396
1397 return (rdata_compare(r1->rdata + offset1, r2->rdata + offset2, length1, length2));
1398 }
1399
1400 // RFC 4034 Section 6.0 states that:
1401 //
1402 // A canonical RR form and ordering within an RRset are required in order to
1403 // construct and verify RRSIG RRs.
1404 //
1405 // This function is called to order within an RRset. We can't just do a memcmp as
1406 // as stated in 6.3. This function is responsible for the third bullet in 6.2, where
1407 // the RDATA has to be converted to lower case if it has domain names.
1408 mDNSlocal int RDATACompare(const void *rdata1, const void *rdata2)
1409 {
1410 rdataComp *r1 = (rdataComp *)rdata1;
1411 rdataComp *r2 = (rdataComp *)rdata2;
1412
1413 if (r1->rrtype != r2->rrtype)
1414 {
1415 LogMsg("RDATACompare: ERROR!! comparing rdata of wrong types type1: %d, type2: %d", r1->rrtype, r2->rrtype);
1416 return -1;
1417 }
1418 switch (r1->rrtype)
1419 {
1420 case kDNSType_A: // 1. Address Record
1421 case kDNSType_NULL: // 10 NULL RR
1422 case kDNSType_WKS: // 11 Well-known-service
1423 case kDNSType_HINFO: // 13 Host information
1424 case kDNSType_TXT: // 16 Arbitrary text string
1425 case kDNSType_X25: // 19 X_25 calling address
1426 case kDNSType_ISDN: // 20 ISDN calling address
1427 case kDNSType_NSAP: // 22 NSAP address
1428 case kDNSType_KEY: // 25 Security key
1429 case kDNSType_GPOS: // 27 Geographical position (withdrawn)
1430 case kDNSType_AAAA: // 28 IPv6 Address
1431 case kDNSType_LOC: // 29 Location Information
1432 case kDNSType_EID: // 31 Endpoint identifier
1433 case kDNSType_NIMLOC: // 32 Nimrod Locator
1434 case kDNSType_ATMA: // 34 ATM Address
1435 case kDNSType_CERT: // 37 Certification record
1436 case kDNSType_A6: // 38 IPv6 Address (deprecated)
1437 case kDNSType_SINK: // 40 Kitchen sink (experimental)
1438 case kDNSType_OPT: // 41 EDNS0 option (meta-RR)
1439 case kDNSType_APL: // 42 Address Prefix List
1440 case kDNSType_DS: // 43 Delegation Signer
1441 case kDNSType_SSHFP: // 44 SSH Key Fingerprint
1442 case kDNSType_IPSECKEY: // 45 IPSECKEY
1443 case kDNSType_RRSIG: // 46 RRSIG
1444 case kDNSType_NSEC: // 47 Denial of Existence
1445 case kDNSType_DNSKEY: // 48 DNSKEY
1446 case kDNSType_DHCID: // 49 DHCP Client Identifier
1447 case kDNSType_NSEC3: // 50 Hashed Authenticated Denial of Existence
1448 case kDNSType_NSEC3PARAM: // 51 Hashed Authenticated Denial of Existence
1449 case kDNSType_HIP: // 55 Host Identity Protocol
1450 case kDNSType_SPF: // 99 Sender Policy Framework for E-Mail
1451 default:
1452 return rdata_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1453 case kDNSType_NS: // 2 Name Server
1454 case kDNSType_MD: // 3 Mail Destination
1455 case kDNSType_MF: // 4 Mail Forwarder
1456 case kDNSType_CNAME: // 5 Canonical Name
1457 case kDNSType_MB: // 7 Mailbox
1458 case kDNSType_MG: // 8 Mail Group
1459 case kDNSType_MR: // 9 Mail Rename
1460 case kDNSType_PTR: // 12 Domain name pointer
1461 case kDNSType_NSAP_PTR: // 23 Reverse NSAP lookup (deprecated)
1462 case kDNSType_DNAME: // 39 Non-terminal DNAME (for IPv6)
1463 return name_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1464 case kDNSType_SRV: // 33 Service record
1465 return srv_compare(r1, r2);
1466 case kDNSType_SOA: // 6 Start of Authority
1467 return soa_compare(r1, r2);
1468
1469 case kDNSType_RP: // 17 Responsible person
1470 case kDNSType_MINFO: // 14 Mailbox information
1471 return dom2_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1472 case kDNSType_MX: // 15 Mail Exchanger
1473 case kDNSType_AFSDB: // 18 AFS cell database
1474 case kDNSType_RT: // 21 Router
1475 case kDNSType_KX: // 36 Key Exchange
1476 return mx_compare(r1, r2);
1477 case kDNSType_PX: // 26 X.400 mail mapping
1478 return px_compare(r1, r2);
1479 case kDNSType_NAPTR: // 35 Naming Authority PoinTeR
1480 return naptr_compare(r1, r2);
1481 case kDNSType_TKEY: // 249 Transaction key
1482 case kDNSType_TSIG: // 250 Transaction signature
1483 // TSIG and TKEY have a domainname followed by data
1484 return tsig_compare(r1, r2);
1485 // TBD: We are comparing them as opaque types, perhaps not right
1486 case kDNSType_SIG: // 24 Security signature
1487 case kDNSType_NXT: // 30 Next domain (security)
1488 LogMsg("RDATACompare: WARNING!! explicit support has not been added, using default");
1489 return rdata_compare(r1->rdata, r2->rdata, r1->rdlength, r2->rdlength);
1490 }
1491 }
1492
1493
1494
1495 // RFC 4034 section 6.2 requirement for verifying signature.
1496 //
1497 // 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1498 // HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
1499 // SRV, DNAME, A6, RRSIG, or NSEC, all uppercase US-ASCII letters in
1500 // the DNS names contained within the RDATA are replaced by the
1501 // corresponding lowercase US-ASCII letters;
1502 //
1503 // NSEC and HINFO is not needed as per dnssec-bis update. RRSIG is done elsewhere
1504 // as part of signature verification
1505 mDNSlocal void ConvertRDATAToCanonical(mDNSu16 rrtype, mDNSu16 rdlength, mDNSu8 *rdata)
1506 {
1507 domainname name;
1508 int len;
1509 mDNSu8 *origRdata = rdata;
1510
1511 // Ensure that we have at least one byte of data to examine and modify.
1512
1513 if (!rdlength) { LogMsg("ConvertRDATAToCanonical: rdlength zero for rrtype %s", DNSTypeName(rrtype)); return; }
1514
1515 switch (rrtype)
1516 {
1517 // Not adding suppot for A6 as it is deprecated
1518 case kDNSType_A6: // 38 IPv6 Address (deprecated)
1519 default:
1520 debugdnssec("ConvertRDATAToCanonical: returning from default %s", DNSTypeName(rrtype));
1521 return;
1522 case kDNSType_NS: // 2 Name Server
1523 case kDNSType_MD: // 3 Mail Destination
1524 case kDNSType_MF: // 4 Mail Forwarder
1525 case kDNSType_CNAME: // 5 Canonical Name
1526 case kDNSType_MB: // 7 Mailbox
1527 case kDNSType_MG: // 8 Mail Group
1528 case kDNSType_MR: // 9 Mail Rename
1529 case kDNSType_PTR: // 12 Domain name pointer
1530 case kDNSType_DNAME: // 39 Non-terminal DNAME (for IPv6)
1531 case kDNSType_NXT: // 30 Next domain (security)
1532
1533 // TSIG and TKEY are not mentioned in RFC 4034, but we just leave it here
1534 case kDNSType_TSIG: // 250 Transaction signature
1535 case kDNSType_TKEY: // 249 Transaction key
1536
1537 if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1538 {
1539 LogMsg("ConvertRDATAToCanonical: ERROR!! DNSNameToLowerCase failed");
1540 return;
1541 }
1542 AssignDomainName((domainname *)rdata, &name);
1543 return;
1544 case kDNSType_MX: // 15 Mail Exchanger
1545 case kDNSType_AFSDB: // 18 AFS cell database
1546 case kDNSType_RT: // 21 Router
1547 case kDNSType_KX: // 36 Key Exchange
1548
1549 // format: preference - 2 bytes, followed by name
1550 // Ensure that we have at least 3 bytes (preference + 1 byte for the domain name)
1551 if (rdlength <= 3)
1552 {
1553 LogMsg("ConvertRDATAToCanonical:MX: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1554 return;
1555 }
1556 if (DNSNameToLowerCase((domainname *)(rdata + 2), &name) != mStatus_NoError)
1557 {
1558 LogMsg("ConvertRDATAToCanonical: MX: ERROR!! DNSNameToLowerCase failed");
1559 return;
1560 }
1561 AssignDomainName((domainname *)(rdata + 2), &name);
1562 return;
1563 case kDNSType_SRV: // 33 Service record
1564 // format : priority, weight and port - 6 bytes, followed by name
1565 if (rdlength <= 7)
1566 {
1567 LogMsg("ConvertRDATAToCanonical:SRV: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1568 return;
1569 }
1570 if (DNSNameToLowerCase((domainname *)(rdata + 6), &name) != mStatus_NoError)
1571 {
1572 LogMsg("ConvertRDATAToCanonical: SRV: ERROR!! DNSNameToLowerCase failed");
1573 return;
1574 }
1575 AssignDomainName((domainname *)(rdata + 6), &name);
1576 return;
1577 case kDNSType_PX: // 26 X.400 mail mapping
1578 if (rdlength <= 3)
1579 {
1580 LogMsg("ConvertRDATAToCanonical:PX: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1581 return;
1582 }
1583 // Preference followed by two domain names
1584 rdata += 2;
1585 /* FALLTHROUGH */
1586 case kDNSType_RP: // 17 Responsible person
1587 case kDNSType_SOA: // 6 Start of Authority
1588 case kDNSType_MINFO: // 14 Mailbox information
1589 if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1590 {
1591 LogMsg("ConvertRDATAToCanonical: SOA1: ERROR!! DNSNameToLowerCase failed");
1592 return;
1593 }
1594
1595 AssignDomainName((domainname *)rdata, &name);
1596 len = DomainNameLength((domainname *)rdata);
1597 if (rdlength <= len + 1)
1598 {
1599 LogMsg("ConvertRDATAToCanonical:RP: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1600 return;
1601 }
1602 rdata += len;
1603
1604 if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1605 {
1606 LogMsg("ConvertRDATAToCanonical: SOA2: ERROR!! DNSNameToLowerCase failed");
1607 return;
1608 }
1609 AssignDomainName((domainname *)rdata, &name);
1610 return;
1611 case kDNSType_NAPTR: // 35 Naming Authority Pointer
1612 // order and preference
1613 rdata += 4;
1614 // Flags (including the length byte)
1615 rdata += (((int) rdata[0]) + 1);
1616 // Service (including the length byte)
1617 rdata += (((int) rdata[0]) + 1);
1618 // regexp (including the length byte)
1619 rdata += (((int) rdata[0]) + 1);
1620
1621 // Replacement field is a domainname. If we have at least one more byte, then we are okay.
1622 if ((origRdata + rdlength) < rdata + 1)
1623 {
1624 LogMsg("ConvertRDATAToCanonical:NAPTR: origRdata %p, rdlength %d, rdata %p for rrtype %s too small", origRdata, rdlength, rdata, DNSTypeName(rrtype));
1625 return;
1626 }
1627 if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1628 {
1629 LogMsg("ConvertRDATAToCanonical: NAPTR2: ERROR!! DNSNameToLowerCase failed");
1630 return;
1631 }
1632 AssignDomainName((domainname *)rdata, &name);
1633 case kDNSType_SIG: // 24 Security signature
1634 // format: <18 bytes> <domainname> <data>
1635 if (rdlength <= 19)
1636 {
1637 LogMsg("ConvertRDATAToCanonical:SIG: rdlength %d for rrtype %s too small", rdlength, DNSTypeName(rrtype));
1638 return;
1639 }
1640 // Preference followed by two domain names
1641 rdata += 18;
1642 if (DNSNameToLowerCase((domainname *)rdata, &name) != mStatus_NoError)
1643 {
1644 LogMsg("ConvertRDATAToCanonical: SIG: ERROR!! DNSNameToLowerCase failed");
1645 return;
1646 }
1647 AssignDomainName((domainname *)rdata, &name);
1648 return;
1649 }
1650 }
1651
1652 mDNSlocal mDNSBool ValidateSignatureWithKey(DNSSECVerifier *dv, RRVerifier *rrset, RRVerifier *keyv, RRVerifier *sig)
1653 {
1654 domainname name;
1655 domainname signerName;
1656 int labels;
1657 mDNSu8 fixedPart[MAX_DOMAIN_NAME + 8]; // domainname + type + class + ttl
1658 int fixedPartLen;
1659 RRVerifier *tmp;
1660 int nrrsets;
1661 rdataComp *ptr, *start, *p;
1662 rdataRRSig *rrsig;
1663 rdataDNSKey *key;
1664 int i;
1665 int sigNameLen;
1666 mDNSu16 temp;
1667 mStatus algRet;
1668
1669
1670 key = (rdataDNSKey *)keyv->rdata;
1671 rrsig = (rdataRRSig *)sig->rdata;
1672
1673 LogDNSSEC("ValidateSignatureWithKey: Validating signature with key with tag %d", (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength));
1674
1675 if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &signerName) != mStatus_NoError)
1676 {
1677 LogMsg("ValidateSignatureWithKey: ERROR!! cannot convert signer name to lower case");
1678 return mDNSfalse;
1679 }
1680
1681 if (DNSNameToLowerCase((domainname *)&rrset->name, &name) != mStatus_NoError)
1682 {
1683 LogMsg("ValidateSignatureWithKey: ERROR!! cannot convert rrset name to lower case");
1684 return mDNSfalse;
1685 }
1686
1687 sigNameLen = DomainNameLength(&signerName);
1688 labels = CountLabels(&name);
1689 // RFC 4034: RRSIG validation
1690 //
1691 // signature = sign(RRSIG_RDATA | RR(1) | RR(2)... )
1692 //
1693 // where RRSIG_RDATA excludes the signature and signer name in canonical form
1694
1695 if (dv->ctx) AlgDestroy(dv->ctx);
1696 dv->ctx = AlgCreate(CRYPTO_ALG, rrsig->alg);
1697 if (!dv->ctx)
1698 {
1699 LogMsg("ValidateSignatureWithKey: ERROR!! No algorithm support for %d", rrsig->alg);
1700 return mDNSfalse;
1701 }
1702 AlgAdd(dv->ctx, (mDNSu8 *)rrsig, RRSIG_FIXED_SIZE);
1703 AlgAdd(dv->ctx, signerName.c, sigNameLen);
1704
1705 if (labels - rrsig->labels > 0)
1706 {
1707 domainname *d;
1708 LogDNSSEC("ValidateSignatureWithKey: ====splitting labels %d, rrsig->labels %d====", labels,rrsig->labels);
1709 d = (domainname *)SkipLeadingLabels(&name, labels - rrsig->labels);
1710 fixedPart[0] = 1;
1711 fixedPart[1] = '*';
1712 AssignDomainName((domainname *)(fixedPart + 2), d);
1713 fixedPartLen = DomainNameLength(d) + 2;
1714 // See RFC 4034 section 3.1.3. If you are looking up *.example.com,
1715 // the labels count in the RRSIG is 2, but this is not considered as
1716 // a wildcard answer
1717 if (name.c[0] != 1 || name.c[1] != '*')
1718 {
1719 LogDNSSEC("ValidateSignatureWithKey: Wildcard exapnded answer for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
1720 dv->flags |= WILDCARD_PROVES_ANSWER_EXPANDED;
1721 dv->wildcardName = (domainname *)SkipLeadingLabels(&dv->origName, labels - rrsig->labels);
1722 if (!dv->wildcardName) return mDNSfalse;
1723 }
1724 }
1725 else
1726 {
1727 debugdnssec("ValidateSignatureWithKey: assigning domainname");
1728 AssignDomainName((domainname *)fixedPart, &name);
1729 fixedPartLen = DomainNameLength(&name);
1730 }
1731 temp = swap16(rrset->rrtype);
1732 mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&temp, sizeof(rrset->rrtype));
1733 fixedPartLen += sizeof(rrset->rrtype);
1734 temp = swap16(rrset->rrclass);
1735 mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&temp, sizeof(rrset->rrclass));
1736 fixedPartLen += sizeof(rrset->rrclass);
1737 mDNSPlatformMemCopy(fixedPart + fixedPartLen, (mDNSu8 *)&rrsig->origTTL, sizeof(rrsig->origTTL));
1738 fixedPartLen += sizeof(rrsig->origTTL);
1739
1740
1741 for (tmp = rrset, nrrsets = 0; tmp; tmp = tmp->next)
1742 nrrsets++;
1743
1744 tmp = rrset;
1745 start = ptr = mDNSPlatformMemAllocate(nrrsets * sizeof (rdataComp));
1746 debugdnssec("ValidateSignatureWithKey: start %p, nrrsets %d", start, nrrsets);
1747 if (ptr)
1748 {
1749 // Need to initialize for failure case below
1750 mDNSPlatformMemZero(ptr, nrrsets * (sizeof (rdataComp)));
1751 while (tmp)
1752 {
1753 ptr->rdlength = tmp->rdlength;
1754 ptr->rrtype = tmp->rrtype;
1755 if (ptr->rdlength)
1756 {
1757 ptr->rdata = mDNSPlatformMemAllocate(ptr->rdlength);
1758 if (ptr->rdata)
1759 mDNSPlatformMemCopy(ptr->rdata, tmp->rdata, tmp->rdlength);
1760 else
1761 {
1762 for (i = 0; i < nrrsets; i++)
1763 if (start[i].rdata) mDNSPlatformMemFree(start[i].rdata);
1764 mDNSPlatformMemFree(start);
1765 LogMsg("ValidateSignatureWithKey:1: ERROR!! RDATA memory alloation failure");
1766 return mDNSfalse;
1767 }
1768 }
1769 ptr++;
1770 tmp = tmp->next;
1771 }
1772 }
1773 else
1774 {
1775 LogMsg("ValidateSignatureWithKey:2: ERROR!! RDATA memory alloation failure");
1776 return mDNSfalse;
1777 }
1778
1779 PrintFixedSignInfo(rrsig, &signerName, sigNameLen, fixedPart, fixedPartLen);
1780
1781 mDNSPlatformQsort(start, nrrsets, sizeof(rdataComp), RDATACompare);
1782 for (p = start, i = 0; i < nrrsets; p++, i++)
1783 {
1784 int rdlen;
1785
1786 // The array is sorted and hence checking adjacent entries for duplicate is sufficient
1787 if (i > 0)
1788 {
1789 rdataComp *q = p - 1;
1790 if (!RDATACompare((void *)p, (void *)q)) continue;
1791 }
1792
1793 // Add the fixed part
1794 AlgAdd(dv->ctx, fixedPart, fixedPartLen);
1795
1796 // Add the rdlength
1797 rdlen = swap16(p->rdlength);
1798 AlgAdd(dv->ctx, (mDNSu8 *)&rdlen, sizeof(mDNSu16));
1799
1800 ConvertRDATAToCanonical(p->rrtype, p->rdlength, p->rdata);
1801
1802 PrintVarSignInfo(rdlen, p->rdata);
1803 AlgAdd(dv->ctx, p->rdata, p->rdlength);
1804 }
1805 // free the memory as we don't need it anymore
1806 for (i = 0; i < nrrsets; i++)
1807 if (start[i].rdata) mDNSPlatformMemFree(start[i].rdata);
1808 mDNSPlatformMemFree(start);
1809
1810 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);
1811 AlgDestroy(dv->ctx);
1812 dv->ctx = mDNSNULL;
1813 if (algRet != mStatus_NoError)
1814 {
1815 LogDNSSEC("ValidateSignatureWithKey: AlgVerify failed for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
1816 // Reset the state if we set any above.
1817 if (dv->flags & WILDCARD_PROVES_ANSWER_EXPANDED)
1818 {
1819 dv->flags &= ~WILDCARD_PROVES_ANSWER_EXPANDED;
1820 dv->wildcardName = mDNSNULL;
1821 }
1822 return mDNSfalse;
1823 }
1824 return mDNStrue;
1825 }
1826
1827 // Walk all the keys and for each key walk all the RRSIGS that signs the original rrset
1828 mDNSlocal mStatus ValidateSignature(DNSSECVerifier *dv, RRVerifier **resultKey, RRVerifier **resultRRSIG)
1829 {
1830 RRVerifier *rrset;
1831 RRVerifier *keyv;
1832 RRVerifier *rrsigv;
1833 RRVerifier *sig;
1834 rdataDNSKey *key;
1835 rdataRRSig *rrsig;
1836 mDNSu16 tag;
1837
1838 rrset = dv->rrset;
1839 sig = dv->rrsig;
1840
1841 for (keyv = dv->key; keyv; keyv = keyv->next)
1842 {
1843 key = (rdataDNSKey *)keyv->rdata;
1844 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
1845 for (rrsigv = sig; rrsigv; rrsigv = rrsigv->next)
1846 {
1847 rrsig = (rdataRRSig *)rrsigv->rdata;
1848 // 7. The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST match the owner
1849 // name, algorithm, and key tag for some DNSKEY RR in the zone's apex DNSKEY RRset.
1850 if (!SameDomainName((domainname *)&rrsig->signerName, &keyv->name))
1851 {
1852 debugdnssec("ValidateSignature: name mismatch");
1853 continue;
1854 }
1855 if (key->alg != rrsig->alg)
1856 {
1857 debugdnssec("ValidateSignature: alg mismatch");
1858 continue;
1859 }
1860 if (tag != swap16(rrsig->keyTag))
1861 {
1862 debugdnssec("ValidateSignature: keyTag mismatch rrsig tag %d(0x%x), keyTag %d(0x%x)", swap16(rrsig->keyTag),
1863 swap16(rrsig->keyTag), tag, tag);
1864 continue;
1865 }
1866 // 8. The matching DNSKEY RR MUST be present in the zone's apex DNSKEY RRset, and MUST
1867 // have the Zone Flag bit (DNSKEY RDATA Flag bit 7) set.
1868 if (!((swap16(key->flags)) & DNSKEY_ZONE_SIGN_KEY))
1869 {
1870 debugdnssec("ValidateSignature: ZONE flag bit not set");
1871 continue;
1872 }
1873 debugdnssec("ValidateSignature:Found a key and RRSIG tag: %d", tag);
1874 if (ValidateSignatureWithKey(dv, rrset, keyv, rrsigv))
1875 {
1876 LogDNSSEC("ValidateSignature: Validated successfully with key tag %d", tag);
1877 *resultKey = keyv;
1878 *resultRRSIG = rrsigv;
1879 return mStatus_NoError;
1880 }
1881 }
1882 }
1883 *resultKey = mDNSNULL;
1884 *resultRRSIG = mDNSNULL;
1885 return mStatus_NoSuchRecord;
1886 }
1887
1888 mDNSlocal mDNSBool ValidateSignatureWithKeyForAllRRSigs(DNSSECVerifier *dv, RRVerifier *rrset, RRVerifier *keyv, RRVerifier *sig)
1889 {
1890 rdataRRSig *rrsig;
1891 mDNSu16 tag;
1892
1893 while (sig)
1894 {
1895 rrsig = (rdataRRSig *)sig->rdata;
1896 tag = (mDNSu16)keytag(keyv->rdata, keyv->rdlength);
1897 if (tag == swap16(rrsig->keyTag))
1898 {
1899 if (ValidateSignatureWithKey(dv, rrset, keyv, sig))
1900 {
1901 LogDNSSEC("ValidateSignatureWithKeyForAllRRSigs: Validated");
1902 return mDNStrue;
1903 }
1904 }
1905 sig = sig->next;
1906 }
1907 return mDNSfalse;
1908 }
1909
1910 mDNSlocal mStatus ValidateDS(DNSSECVerifier *dv)
1911 {
1912 mDNSu8 *digest;
1913 int digestLen;
1914 domainname name;
1915 rdataRRSig *rrsig;
1916 rdataDS *ds;
1917 rdataDNSKey *key;
1918 RRVerifier *keyv;
1919 RRVerifier *dsv;
1920 mStatus algRet;
1921
1922 rrsig = (rdataRRSig *)dv->rrsig->rdata;
1923
1924 // Walk all the DS Records to see if we have a matching DNS KEY record that verifies
1925 // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
1926 // this zone. Loop till we find one.
1927 for (dsv = dv->ds; dsv; dsv = dsv->next)
1928 {
1929 ds = (rdataDS *)dsv->rdata;
1930 if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
1931 {
1932 LogDNSSEC("ValidateDS: Unsupported digest %d", ds->digestType);
1933 return mStatus_BadParamErr;
1934 }
1935 else debugdnssec("ValidateDS: digest type %d", ds->digestType);
1936 for (keyv = dv->key; keyv; keyv = keyv->next)
1937 {
1938 key = (rdataDNSKey *)keyv->rdata;
1939 mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
1940 if (tag != swap16(ds->keyTag))
1941 {
1942 debugdnssec("ValidateDS:Not a valid keytag %d", tag);
1943 continue;
1944 }
1945
1946 if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &name) != mStatus_NoError)
1947 {
1948 LogMsg("ValidateDS: ERROR!! cannot convert to lower case");
1949 continue;
1950 }
1951
1952 if (dv->ctx) AlgDestroy(dv->ctx);
1953 dv->ctx = AlgCreate(DIGEST_ALG, ds->digestType);
1954 if (!dv->ctx)
1955 {
1956 LogMsg("ValidateDS: ERROR!! Cannot allocate context");
1957 continue;
1958 }
1959 digest = (mDNSu8 *)&ds->digest;
1960 digestLen = dsv->rdlength - DS_FIXED_SIZE;
1961
1962 AlgAdd(dv->ctx, name.c, DomainNameLength(&name));
1963 AlgAdd(dv->ctx, key, keyv->rdlength);
1964
1965 algRet = AlgVerify(dv->ctx, mDNSNULL, 0, digest, digestLen);
1966 AlgDestroy(dv->ctx);
1967 dv->ctx = mDNSNULL;
1968 if (algRet == mStatus_NoError)
1969 {
1970 LogDNSSEC("ValidateDS: DS Validated Successfully, need to verify the key %d", tag);
1971 // We found the DNS KEY that is authenticated by the DS in our parent zone. Check to see if this key
1972 // was used to sign the DNS KEY RRSET. If so, then the keys in our DNS KEY RRSET are valid
1973 if (ValidateSignatureWithKeyForAllRRSigs(dv, dv->key, keyv, dv->rrsigKey))
1974 {
1975 LogDNSSEC("ValidateDS: DS Validated Successfully %d", tag);
1976 return mStatus_NoError;
1977 }
1978 }
1979 }
1980 }
1981 return mStatus_NoSuchRecord;
1982 }
1983
1984 mDNSlocal mDNSBool UnlinkRRVerifier(DNSSECVerifier *dv, RRVerifier *elem, RRVerifierSet set)
1985 {
1986 RRVerifier **v;
1987
1988 switch (set)
1989 {
1990 case RRVS_rr:
1991 v = &dv->rrset;
1992 break;
1993 case RRVS_rrsig:
1994 v = &dv->rrsig;
1995 break;
1996 case RRVS_key:
1997 v = &dv->key;
1998 break;
1999 case RRVS_rrsig_key:
2000 v = &dv->rrsigKey;
2001 break;
2002 case RRVS_ds:
2003 v = &dv->ds;
2004 break;
2005 default:
2006 LogMsg("UnlinkRRVerifier: ERROR!! default case %d", set);
2007 return mDNSfalse;
2008 }
2009 while (*v && *v != elem)
2010 v = &(*v)->next;
2011 if (!(*v))
2012 {
2013 LogMsg("UnlinkRRVerifier: ERROR!! cannot find element in set %d", set);
2014 return mDNSfalse;
2015 }
2016 *v = elem->next; // Cut this record from the list
2017 elem->next = mDNSNULL;
2018 return mDNStrue;
2019 }
2020
2021 // This can link a single AuthChain element or a list of AuthChain elements to
2022 // DNSSECVerifier. The latter happens when we have multiple NSEC proofs and
2023 // we gather up all the proofs in one place.
2024 mDNSexport void AuthChainLink(DNSSECVerifier *dv, AuthChain *ae)
2025 {
2026 AuthChain *head;
2027
2028 LogDNSSEC("AuthChainLink: called");
2029
2030 head = ae;
2031 // Get to the last element
2032 while (ae->next)
2033 ae = ae->next;
2034 *(dv->actail) = head; // Append this record to tail of auth chain
2035 dv->actail = &(ae->next); // Advance tail pointer
2036 }
2037
2038 mDNSlocal mDNSBool AuthChainAdd(DNSSECVerifier *dv, RRVerifier *resultKey, RRVerifier *resultRRSig)
2039 {
2040 AuthChain *ae;
2041 rdataDNSKey *key;
2042 mDNSu16 tag;
2043
2044 if (!dv->rrset || !resultKey || !resultRRSig)
2045 {
2046 LogMsg("AuthChainAdd: ERROR!! input argument NULL");
2047 return mDNSfalse;
2048 }
2049
2050 // Unlink resultKey and resultRRSig and store as part of AuthChain
2051 if (!UnlinkRRVerifier(dv, resultKey, RRVS_key))
2052 {
2053 LogMsg("AuthChainAdd: ERROR!! cannot unlink key");
2054 return mDNSfalse;
2055 }
2056 if (!UnlinkRRVerifier(dv, resultRRSig, RRVS_rrsig))
2057 {
2058 LogMsg("AuthChainAdd: ERROR!! cannot unlink rrsig");
2059 return mDNSfalse;
2060 }
2061
2062 ae = mDNSPlatformMemAllocate(sizeof(AuthChain));
2063 if (!ae)
2064 {
2065 LogMsg("AuthChainAdd: AuthChain alloc failure");
2066 return mDNSfalse;
2067 }
2068
2069 ae->next = mDNSNULL;
2070 ae->rrset = dv->rrset;
2071 dv->rrset = mDNSNULL;
2072
2073 ae->rrsig = resultRRSig;
2074 ae->key = resultKey;
2075
2076 key = (rdataDNSKey *)resultKey->rdata;
2077 tag = (mDNSu16)keytag((mDNSu8 *)key, resultKey->rdlength);
2078 LogDNSSEC("AuthChainAdd: inserting AuthChain element with rrset %##s (%s), DNSKEY tag %d", ae->rrset->name.c, DNSTypeName(ae->rrset->rrtype), tag);
2079
2080 AuthChainLink(dv, ae);
2081 return mDNStrue;
2082 }
2083
2084 // RFC 4035: Section 5.3.3
2085 //
2086 // If the resolver accepts the RRset as authentic, the validator MUST set the TTL of
2087 // the RRSIG RR and each RR in the authenticated RRset to a value no greater than the
2088 // minimum of:
2089 //
2090 // o the RRset's TTL as received in the response;
2091 //
2092 // o the RRSIG RR's TTL as received in the response;
2093 //
2094 // o the value in the RRSIG RR's Original TTL field; and
2095 //
2096 // o the difference of the RRSIG RR's Signature Expiration time and the
2097 // current time.
2098 mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
2099 {
2100 DNSQuestion question;
2101 CacheRecord *rr;
2102 RRVerifier *rv;
2103 rdataRRSig *rrsig;
2104 mDNSu32 slot;
2105 CacheGroup *cg;
2106 int sigNameLen, len;
2107 mDNSu8 *ptr;
2108 mDNSu32 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL;
2109 domainname *qname;
2110 mDNSu16 qtype;
2111 CacheRecord *rrsigRR;
2112
2113 debugdnssec("SetTTLRRSet called");
2114
2115 // TBD: Just handle secure for now
2116 if (status != DNSSEC_Secure) return;
2117
2118 // check to make sure we built a AuthChain as part of verification
2119 if (!dv->ac || !dv->ac->rrset || !dv->ac->rrsig || !dv->ac->key)
2120 {
2121 LogMsg("SetTTLRRSet: ERROR!! NULL element in chain");
2122 FreeDNSSECVerifier(m, dv);
2123 return;
2124 }
2125
2126 mDNSPlatformMemZero(&question, sizeof(DNSQuestion));
2127 rrTTL = rrsigTTL = rrsigOrigTTL = rrsigTimeTTL = 0;
2128
2129 // 1. Locate the rrset name and get its TTL (take the first one as a representative
2130 // of the rrset).
2131 qname = &dv->origName;
2132 qtype = dv->origType;
2133
2134 question.ThisQInterval = -1;
2135 InitializeQuestion(m, &question, dv->InterfaceID, qname, qtype, mDNSNULL, mDNSNULL);
2136 slot = HashSlot(&question.qname);
2137 cg = CacheGroupForName(m, slot, question.qnamehash, &question.qname);
2138
2139 if (!cg) { LogMsg("SetTTLRRSet cg NULL"); return; }
2140 for (rr = cg->members; rr; rr = rr->next)
2141 if (SameNameRecordAnswersQuestion(&rr->resrec, &question))
2142 {
2143 rrTTL = rr->resrec.rroriginalttl;
2144 break;
2145 }
2146
2147 // Should we check to see if it matches the record in dv->ac->rrset ?
2148 if (!rr)
2149 {
2150 LogMsg("SetTTLRRSet: ERROR!! cannot locate main rrset for %##s (%s)", qname->c, DNSTypeName(qtype));
2151 return;
2152 }
2153
2154
2155 // 2. Get the RRSIG ttl. For NSEC records we need to get the NSEC record's TTL as
2156 // the negative cache record that we created may not be right.
2157
2158 rv = dv->ac->rrsig;
2159 rrsig = (rdataRRSig *)rv->rdata;
2160 sigNameLen = DomainNameLength((domainname *)&rrsig->signerName);
2161 // pointer to signature and the length
2162 ptr = (mDNSu8 *)(rv->rdata + sigNameLen + RRSIG_FIXED_SIZE);
2163 len = rv->rdlength - RRSIG_FIXED_SIZE - sigNameLen;
2164
2165 rrsigRR = mDNSNULL;
2166 if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)
2167 {
2168 CacheRecord *ncr;
2169 rrTTL = 0;
2170 for (ncr = rr->nsec; ncr; ncr = ncr->next)
2171 {
2172 if (ncr->resrec.rrtype == kDNSType_NSEC)
2173 {
2174 rrTTL = ncr->resrec.rroriginalttl;
2175 debugdnssec("SetTTLRRSet: NSEC TTL %u", rrTTL);
2176 }
2177 // Note: we can't use dv->origName here as the NSEC record's RRSIG may not match
2178 // the original name
2179 if (ncr->resrec.rrtype == kDNSType_RRSIG && SameDomainName(ncr->resrec.name, &rv->name))
2180 {
2181 RDataBody2 *rdb = (RDataBody2 *)ncr->resrec.rdata->u.data;
2182 rdataRRSig *sig = (rdataRRSig *)rdb->data;
2183 if (rv->rdlength != ncr->resrec.rdlength)
2184 {
2185 debugdnssec("SetTTLRRSet length mismatch");
2186 continue;
2187 }
2188 if (mDNSPlatformMemSame(sig, rrsig, rv->rdlength))
2189 {
2190 rrsigTTL = ncr->resrec.rroriginalttl;
2191 rrsigOrigTTL = swap32(rrsig->origTTL);
2192 rrsigTimeTTL = swap32(rrsig->sigExpireTime) - swap32(rrsig->sigInceptTime);
2193 }
2194 }
2195 if (rrTTL && rrsigTTL) break;
2196 }
2197 }
2198 else
2199 {
2200 // Look for the matching RRSIG so that we can get its TTL
2201 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2202 if (rr->resrec.rrtype == kDNSType_RRSIG && SameDomainName(rr->resrec.name, &rv->name))
2203 {
2204 RDataBody2 *rdb = (RDataBody2 *)rr->resrec.rdata->u.data;
2205 rdataRRSig *sig = (rdataRRSig *)rdb->data;
2206 if (rv->rdlength != rr->resrec.rdlength)
2207 {
2208 debugdnssec("SetTTLRRSet length mismatch");
2209 continue;
2210 }
2211 if (mDNSPlatformMemSame(sig, rrsig, rv->rdlength))
2212 {
2213 rrsigTTL = rr->resrec.rroriginalttl;
2214 rrsigOrigTTL = swap32(rrsig->origTTL);
2215 rrsigTimeTTL = swap32(rrsig->sigExpireTime) - swap32(rrsig->sigInceptTime);
2216 rrsigRR = rr;
2217 break;
2218 }
2219 }
2220 }
2221
2222 if (!rrTTL || !rrsigTTL || !rrsigOrigTTL || !rrsigTimeTTL)
2223 {
2224 LogMsg("SetTTLRRSet: ERROR!! Bad TTL rrtl %u, rrsigTTL %u, rrsigOrigTTL %u, rrsigTimeTTL %u for %##s (%s)",
2225 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL, qname->c, DNSTypeName(qtype));
2226 return;
2227 }
2228 else
2229 {
2230 LogDNSSEC("SetTTLRRSet: TTL rrtl %u, rrsigTTL %u, rrsigOrigTTL %u, rrsigTimeTTL %u for %##s (%s)",
2231 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL, qname->c, DNSTypeName(qtype));
2232 }
2233
2234 if (rrsigTTL < rrTTL)
2235 rrTTL = rrsigTTL;
2236 if (rrsigOrigTTL < rrTTL)
2237 rrTTL = rrsigOrigTTL;
2238 if (rrsigTimeTTL < rrTTL)
2239 rrTTL = rrsigTimeTTL;
2240
2241 // Set the rrsig's TTL. For NSEC records, rrsigRR is NULL which means it expires when
2242 // the negative cache record expires.
2243 if (rrsigRR)
2244 rrsigRR->resrec.rroriginalttl = rrTTL;
2245
2246 // Find the RRset and set its TTL
2247 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2248 {
2249 if (SameNameRecordAnswersQuestion(&rr->resrec, &question))
2250 {
2251 LogDNSSEC("SetTTLRRSet: Setting the TTL %d for %s, question %##s (%s)", rrTTL, CRDisplayString(m, rr),
2252 question.qname.c, DNSTypeName(rr->resrec.rrtype));
2253 rr->resrec.rroriginalttl = rrTTL;
2254 SetNextCacheCheckTimeForRecord(m, rr);
2255 }
2256 }
2257 }
2258
2259 mDNSlocal void FinishDNSSECVerification(mDNS *const m, DNSSECVerifier *dv)
2260 {
2261 RRVerifier *resultKey;
2262 RRVerifier *resultRRSig;
2263
2264 LogDNSSEC("FinishDNSSECVerification: all rdata sets available for sig verification for %##s (%s)",
2265 dv->origName.c, DNSTypeName(dv->origType));
2266
2267 mDNS_StopQuery(m, &dv->q);
2268 if (ValidateSignature(dv, &resultKey, &resultRRSig) == mStatus_NoError)
2269 {
2270 rdataDNSKey *key;
2271 mDNSu16 tag;
2272 key = (rdataDNSKey *)resultKey->rdata;
2273 tag = (mDNSu16)keytag((mDNSu8 *)key, resultKey->rdlength);
2274
2275 LogDNSSEC("FinishDNSSECVerification: RRSIG validated by DNSKEY tag %d, %##s (%s)", tag, dv->rrset->name.c,
2276 DNSTypeName(dv->rrset->rrtype));
2277
2278 if (TrustedKey(m, dv) == mStatus_NoError)
2279 {
2280 // Need to call this after we called TrustedKey, as AuthChainAdd
2281 // unlinks the resultKey and resultRRSig
2282 if (!AuthChainAdd(dv, resultKey, resultRRSig))
2283 {
2284 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2285 return;
2286 }
2287 // The callback will be called when NSEC verification is done.
2288 if ((dv->flags & WILDCARD_PROVES_ANSWER_EXPANDED))
2289 {
2290 WildcardAnswerProof(m, dv);
2291 return;
2292 }
2293 else
2294 {
2295 dv->DVCallback(m, dv, DNSSEC_Secure);
2296 return;
2297 }
2298 }
2299 if (!ValidateDS(dv))
2300 {
2301 // Need to call this after we called ValidateDS, as AuthChainAdd
2302 // unlinks the resultKey and resultRRSig
2303 if (!AuthChainAdd(dv, resultKey, resultRRSig))
2304 {
2305 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2306 return;
2307 }
2308 FreeDNSSECVerifierRRSets(dv);
2309 dv->recursed++;
2310 if (dv->recursed < MAX_RECURSE_COUNT)
2311 {
2312 LogDNSSEC("FinishDNSSECVerification: Recursion level %d for %##s (%s)", dv->recursed, dv->origName.c,
2313 DNSTypeName(dv->origType));
2314 VerifySignature(m, dv, &dv->q);
2315 return;
2316 }
2317 }
2318 else
2319 {
2320 LogDNSSEC("FinishDNSSECVerification: ValidateDS failed %##s (%s)", dv->rrset->name.c, DNSTypeName(dv->rrset->rrtype));
2321 dv->DVCallback(m, dv, DNSSEC_Insecure);
2322 return;
2323 }
2324 }
2325 else
2326 {
2327 LogDNSSEC("FinishDNSSECVerification: Could not validate the rrset %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2328 dv->DVCallback(m, dv, DNSSEC_Insecure);
2329 return;
2330 }
2331 }
2332
2333 mDNSexport void StartDNSSECVerification(mDNS *const m, DNSSECVerifier *dv)
2334 {
2335 mDNSBool done;
2336
2337 done = GetAllRRSetsForVerification(m, dv);
2338 if (done)
2339 {
2340 if (dv->next != RRVS_done)
2341 LogMsg("StartDNSSECVerification: ERROR!! dv->next is not done");
2342 else
2343 LogDNSSEC("StartDNSSECVerification: all rdata sets available for sig verification");
2344 FinishDNSSECVerification(m, dv);
2345 return;
2346 }
2347 else debugdnssec("StartDNSSECVerification: all rdata sets not available for sig verification next %d", dv->next);
2348 }
2349
2350 mDNSlocal char *DNSSECStatusName(DNSSECStatus status)
2351 {
2352 switch (status)
2353 {
2354 case DNSSEC_Secure: return "Secure";
2355 case DNSSEC_Insecure: return "Insecure";
2356 case DNSSEC_Indeterminate: return "Indeterminate";
2357 case DNSSEC_Bogus: return "Bogus";
2358 default: return "Invalid";
2359 }
2360 }
2361
2362 // We could not use GenerateNegativeResponse as it assumes m->CurrentQuestion to be set. Even if
2363 // we change that, we needs to fix its callers and so on. It is much simpler to call the callback.
2364 mDNSlocal void DeliverDNSSECStatus(mDNS *const m, ResourceRecord *answer, DNSSECStatus status)
2365 {
2366
2367 // Can't use m->CurrentQuestion as it may already be in use
2368 if (m->ValidationQuestion)
2369 LogMsg("DeliverDNSSECStatus: ERROR!! m->ValidationQuestion already set: %##s (%s)",
2370 m->ValidationQuestion->qname.c, DNSTypeName(m->ValidationQuestion->qtype));
2371
2372 m->ValidationQuestion = m->Questions;
2373 while (m->ValidationQuestion && m->ValidationQuestion != m->NewQuestions)
2374 {
2375 DNSQuestion *q = m->ValidationQuestion;
2376
2377 if (q->ValidatingResponse || !q->ValidationRequired ||
2378 (q->ValidationState != DNSSECValInProgress) || !ResourceRecordAnswersQuestion(answer, q))
2379 {
2380 m->ValidationQuestion = q->next;
2381 continue;
2382 }
2383
2384 q->ValidationState = DNSSECValDone;
2385 q->ValidationStatus = status;
2386
2387 MakeNegativeCacheRecord(m, &largerec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL);
2388 if (q->qtype == answer->rrtype || status != DNSSEC_Secure)
2389 {
2390 LogDNSSEC("DeliverDNSSECStatus: Generating dnssec status %s for %##s (%s)", DNSSECStatusName(status),
2391 q->qname.c, DNSTypeName(q->qtype));
2392 if (q->QuestionCallback) q->QuestionCallback(m, q, &largerec.r.resrec, QC_dnssec);
2393 }
2394 else
2395 {
2396 LogDNSSEC("DeliverDNSSECStatus: Following CNAME dnssec status %s for %##s (%s)", DNSSECStatusName(status),
2397 q->qname.c, DNSTypeName(q->qtype));
2398 mDNS_Lock(m);
2399 AnswerQuestionByFollowingCNAME(m, q, answer);
2400 mDNS_Unlock(m);
2401 }
2402
2403 if (m->ValidationQuestion == q) // If m->ValidationQuestion was not auto-advanced, do it ourselves now
2404 m->ValidationQuestion = q->next;
2405 }
2406 m->ValidationQuestion = mDNSNULL;
2407 }
2408
2409 mDNSlocal void DNSSECPositiveValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
2410 {
2411 RRVerifier *rrset;
2412 RRVerifier *rv;
2413 CacheGroup *cg;
2414 CacheRecord *cr;
2415 mDNSu32 slot, namehash;
2416 mDNSu16 rrtype, rrclass;
2417 CacheRecord *const lrr = &largerec.r;
2418 ResourceRecord *answer = mDNSNULL;
2419
2420 LogDNSSEC("DNSSECPositiveValidationCB: called status %s", DNSSECStatusName(status));
2421
2422 //
2423 // 1. Check to see if the rrset that was validated is the same as in cache. If they are not same,
2424 // this validation result is not valid. When the rrset changed while the validation was in
2425 // progress, the act of delivering the changed rrset again should have kicked off another
2426 // verification.
2427 //
2428 // 2. Walk the question list to find the matching question. The original question that started
2429 // the DNSSEC verification may or may not be there. As long as there is a matching question
2430 // and waiting for the response, deliver the response.
2431 //
2432 // 3. If we are answering with CNAME, it is time to follow the CNAME if the response is secure
2433
2434 slot = HashSlot(&dv->origName);
2435 namehash = DomainNameHashValue(&dv->origName);
2436
2437 cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName);
2438 if (!cg)
2439 {
2440 LogDNSSEC("DNSSECPositiveValidationCB: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2441 goto done;
2442 }
2443 if (!dv->ac)
2444 {
2445 // If we don't have the AuthChain, it means we could not validate the rrset. Locate the
2446 // original question based on dv->origName, dv->origType.
2447 InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->origName, dv->origType, mDNSNULL, mDNSNULL);
2448 // Need to be reset ValidatingResponse as we are looking for the cache record that would answer
2449 // the original question
2450 dv->q.ValidatingResponse = mDNSfalse;
2451 for (cr = cg->members; cr; cr = cr->next)
2452 {
2453 if (SameNameRecordAnswersQuestion(&cr->resrec, &dv->q))
2454 {
2455 answer = &cr->resrec;
2456 break;
2457 }
2458 }
2459 }
2460 else
2461 {
2462 if (!dv->ac->rrset)
2463 {
2464 LogMsg("DNSSECPositiveValidationCB: ERROR!! Validated RRSET NULL");
2465 goto done;
2466 }
2467
2468 rrset = dv->ac->rrset;
2469 rrtype = rrset->rrtype;
2470 rrclass = rrset->rrclass;
2471
2472 lrr->resrec.name = &largerec.namestorage;
2473
2474 for (rv = dv->ac->rrset; rv; rv = rv->next)
2475 rv->found = 0;
2476
2477 // Check to see if we can find all the elements in the rrset
2478 for (cr = cg ? cg->members : mDNSNULL; cr; cr = cr->next)
2479 {
2480 if (cr->resrec.rrtype == rrtype && cr->resrec.rrclass == rrclass)
2481 {
2482 for (rv = dv->ac->rrset; rv; rv = rv->next)
2483 {
2484 if (rv->rdlength == cr->resrec.rdlength && rv->rdatahash == cr->resrec.rdatahash)
2485 {
2486 lrr->resrec.namehash = rv->namehash;
2487 lrr->resrec.rrtype = rv->rrtype;
2488 lrr->resrec.rrclass = rv->rrclass;
2489 lrr->resrec.rdata = (RData*)&lrr->smallrdatastorage;
2490 lrr->resrec.rdata->MaxRDLength = MaximumRDSize;
2491
2492 // Convert the "rdata" to a suitable form before we can call SameRDataBody which expects
2493 // some of the resource records in host order and also domainnames fully expanded. We
2494 // converted the resource records into network order for verification purpose and hence
2495 // need to convert them back again before comparing them.
2496 if (!SetRData(mDNSNULL, rv->rdata, rv->rdata + rv->rdlength, &largerec, rv->rdlength))
2497 {
2498 LogMsg("DNSSECPositiveValidationCB: SetRData failed for %##s (%s)", rv->name.c, DNSTypeName(rv->rrtype));
2499 }
2500 else if (SameRDataBody(&cr->resrec, &lrr->resrec.rdata->u, SameDomainName))
2501 {
2502 answer = &cr->resrec;
2503 rv->found = 1;
2504 break;
2505 }
2506 }
2507 }
2508 if (!rv)
2509 {
2510 // The validated rrset does not have the element in the cache, re-validate
2511 LogDNSSEC("DNSSECPositiveValidationCB: CacheRecord %s, not found in the validated set", CRDisplayString(m, cr));
2512 goto done;
2513 }
2514 }
2515 }
2516 // Check to see if we have elements that were not in the cache
2517 for (rv = dv->ac->rrset; rv; rv = rv->next)
2518 {
2519 if (!rv->found)
2520 {
2521 // We had more elements in the validated set, re-validate
2522 LogDNSSEC("DNSSECPositiveValidationCB: Record %##s (%s) not found in the cache", rv->name.c, DNSTypeName(rv->rrtype));
2523 goto done;
2524 }
2525 }
2526 }
2527
2528 // It is not an error for things to disappear underneath
2529 if (!answer)
2530 {
2531 LogDNSSEC("DNSSECPositiveValidationCB: answer NULL");
2532 goto done;
2533 }
2534
2535 DeliverDNSSECStatus(m, answer, status);
2536 SetTTLRRSet(m, dv, status);
2537
2538 done:
2539 FreeDNSSECVerifier(m, dv);
2540 }
2541
2542 mDNSlocal void DNSSECNegativeValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
2543 {
2544 RRVerifier *rv;
2545 CacheGroup *cg;
2546 CacheRecord *cr;
2547 mDNSu32 slot, namehash;
2548 mDNSu16 rrtype, rrclass;
2549 ResourceRecord *answer = mDNSNULL;
2550 AuthChain *ac;
2551
2552 LogDNSSEC("DNSSECNegativeValidationCB: called %s", DNSSECStatusName(status));
2553
2554 // 1. Locate the negative cache record and check the cached NSEC records to see if it matches the
2555 // NSECs that were valiated. If the cached NSECS changed while the validation was in progress,
2556 // we ignore the validation results.
2557 //
2558 // 2. Walk the question list to find the matching question. The original question that started
2559 // the DNSSEC verification may or may not be there. As long as there is a matching question
2560 // and waiting for the response, deliver the response.
2561 //
2562 slot = HashSlot(&dv->origName);
2563 namehash = DomainNameHashValue(&dv->origName);
2564
2565 cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName);
2566 if (!cg)
2567 {
2568 LogDNSSEC("DNSSECNegativeValidationCB: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2569 goto done;
2570 }
2571 if (!dv->ac)
2572 {
2573 // If we don't have the AuthChain, it means we could not validate the rrset. Locate the
2574 // original question based on dv->origName, dv->origType.
2575 InitializeQuestion(m, &dv->q, dv->InterfaceID, &dv->origName, dv->origType, mDNSNULL, mDNSNULL);
2576 // Need to be reset ValidatingResponse as we are looking for the cache record that would answer
2577 // the original question
2578 dv->q.ValidatingResponse = mDNSfalse;
2579 for (cr = cg->members; cr; cr = cr->next)
2580 {
2581 if (SameNameRecordAnswersQuestion(&cr->resrec, &dv->q))
2582 {
2583 answer = &cr->resrec;
2584 break;
2585 }
2586 }
2587 }
2588 else
2589 {
2590 if (!dv->ac->rrset)
2591 {
2592 LogMsg("DNSSECNegativeValidationCB: ERROR!! Validated RRSET NULL");
2593 goto done;
2594 }
2595
2596 rrtype = dv->origType;
2597 rrclass = dv->ac->rrset->rrclass;
2598
2599 for (ac = dv->ac; ac; ac = ac->next)
2600 {
2601 for (rv = ac->rrset; rv; rv = rv->next)
2602 {
2603 if (rv->rrtype == kDNSType_NSEC)
2604 rv->found = 0;
2605 }
2606 }
2607
2608 // Check to see if we can find all the elements in the rrset
2609 for (cr = cg->members; cr; cr = cr->next)
2610 {
2611 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative &&
2612 cr->resrec.rrtype == rrtype && cr->resrec.rrclass == rrclass)
2613 {
2614 CacheRecord *ncr;
2615 for (ncr = cr->nsec; ncr; ncr = ncr->next)
2616 {
2617 // We have RRSIGs for the NSECs cached there too
2618 if (ncr->resrec.rrtype != kDNSType_NSEC)
2619 continue;
2620 for (ac = dv->ac; ac; ac = ac->next)
2621 {
2622 for (rv = ac->rrset; rv; rv = rv->next)
2623 {
2624 if (rv->rrtype == kDNSType_NSEC && rv->rdlength == ncr->resrec.rdlength &&
2625 rv->rdatahash == ncr->resrec.rdatahash)
2626 {
2627 if (SameDomainName(ncr->resrec.name, &rv->name) &&
2628 SameRDataBody(&ncr->resrec, (const RDataBody *)rv->rdata, SameDomainName))
2629 {
2630 LogDNSSEC("DNSSECNegativeValidationCB: setting found %s", CRDisplayString(m, ncr));
2631 answer = &cr->resrec;
2632 rv->found = 1;
2633 break;
2634 }
2635 }
2636 }
2637 if (rv)
2638 break;
2639 }
2640 }
2641 if (!rv)
2642 {
2643 // The validated rrset does not have the element in the cache, re-validate
2644 LogDNSSEC("DNSSECNegativeValidationCB: CacheRecord %s, not found in the validated set", CRDisplayString(m, cr));
2645 goto done;
2646 }
2647 }
2648 }
2649 // Check to see if we have elements that were not in the cache
2650 for (ac = dv->ac; ac; ac = ac->next)
2651 {
2652 for (rv = ac->rrset; rv; rv = rv->next)
2653 {
2654 if (rv->rrtype == kDNSType_NSEC)
2655 {
2656 if (!rv->found)
2657 {
2658 // We had more elements in the validated set, re-validate
2659 LogDNSSEC("DNSSECNegativeValidationCB: Record %##s (%s) not found in the cache", rv->name.c, DNSTypeName(rv->rrtype));
2660 goto done;
2661 }
2662 rv->found = 0;
2663 }
2664 }
2665 }
2666 }
2667
2668 // It is not an error for things to disappear underneath
2669 if (!answer)
2670 {
2671 LogDNSSEC("DNSSECNegativeValidationCB: answer NULL");
2672 goto done;
2673 }
2674
2675 DeliverDNSSECStatus(m, answer, status);
2676 SetTTLRRSet(m, dv, status);
2677
2678 done:
2679 FreeDNSSECVerifier(m, dv);
2680 }
2681
2682 mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
2683 {
2684 mDNSu32 slot = HashSlot(&q->qname);
2685 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
2686 CacheRecord *rr;
2687
2688 LogDNSSEC("VerifySignature called for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2689 if (!dv)
2690 {
2691 if (!q->qDNSServer || q->qDNSServer->cellIntf)
2692 {
2693 LogDNSSEC("VerifySignature: Disabled");
2694 return;
2695 }
2696 // We assume that the verifier's question has been initialized here so that ValidateWithNSECS below
2697 // knows what it has prove the non-existence of.
2698 dv = AllocateDNSSECVerifier(m, &q->qname, q->qtype, q->InterfaceID, DNSSECPositiveValidationCB, VerifySigCallback);
2699 if (!dv) { LogMsg("VerifySignature: ERROR!! memory alloc failed"); return; }
2700 }
2701
2702 // If we find a CNAME response to the question, remember what qtype
2703 // caused the CNAME response. origType is not sufficient as we
2704 // recursively validate the response and origType is initialized above
2705 // the first time this function is called.
2706 dv->currQtype = q->qtype;
2707
2708 // Walk the cache and get all the rrsets for verification.
2709 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2710 if (SameNameRecordAnswersQuestion(&rr->resrec, q))
2711 {
2712 // We also get called for RRSIGs which matches qtype. We don't need that here as we are
2713 // building rrset for matching q->qname. Checking for RRSIG type is important as otherwise
2714 // we would miss the CNAME answering any qtype.
2715 if (rr->resrec.rrtype == kDNSType_RRSIG && rr->resrec.rrtype != q->qtype)
2716 {
2717 LogDNSSEC("VerifySignature: Question %##s (%s) answered with RRSIG record %s, not using it", q->qname.c, DNSTypeName(q->qtype), CRDisplayString(m, rr));
2718 continue;
2719 }
2720
2721 // See DNSSECRecordAnswersQuestion: This should never happen. NSEC records are
2722 // answered directly only when the qtype is NSEC. Otherwise, NSEC records are
2723 // used only for denial of existence and hence should go through negative cache
2724 // entry.
2725 if (rr->resrec.rrtype == kDNSType_NSEC && q->qtype != kDNSType_NSEC)
2726 {
2727 LogMsg("VerifySignature: ERROR!! Question %##s (%s) answered using NSEC record %s", q->qname.c, DNSTypeName(q->qtype), CRDisplayString(m, rr));
2728 continue;
2729 }
2730
2731 // We might get a NSEC response when we first send the query out from the "core" for ValidationRequired
2732 // questions. Later as part of validating the response, we might get a NSEC response.
2733 if (rr->resrec.RecordType == kDNSRecordTypePacketNegative && DNSSECQuestion(q))
2734 {
2735 dv->DVCallback = DNSSECNegativeValidationCB;
2736 // If we can't find the NSEC, we can't validate. This can happens if we are
2737 // behind a non-DNSSEC aware CPE/server.
2738 if (!rr->nsec)
2739 {
2740 LogDNSSEC("VerifySignature: No nsecs found for %s", CRDisplayString(m, rr));
2741 dv->DVCallback(m, dv, DNSSEC_Insecure);
2742 return;
2743 }
2744 ValidateWithNSECS(m, dv, rr);
2745 return;
2746 }
2747
2748 if (AddRRSetToVerifier(dv, &rr->resrec, mDNSNULL, RRVS_rr) != mStatus_NoError)
2749 {
2750 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2751 return;
2752 }
2753 }
2754 if (!dv->rrset)
2755 {
2756 LogMsg("VerifySignature: rrset mDNSNULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
2757 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2758 return;
2759 }
2760 dv->next = RRVS_rrsig;
2761 StartDNSSECVerification(m, dv);
2762 }
2763
2764
2765 mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv)
2766 {
2767 rdataRRSig *rrsig;
2768 rdataDS *ds;
2769 rdataDNSKey *key;
2770 TrustAnchor *ta;
2771 RRVerifier *keyv;
2772
2773 rrsig = (rdataRRSig *)dv->rrsig->rdata;
2774
2775 // Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies
2776 // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
2777 // this zone. Loop till we find one.
2778 for (ta = m->TrustAnchors; ta; ta = ta->next)
2779 {
2780 ds = (rdataDS *)&ta->rds;
2781 if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
2782 {
2783 LogMsg("TrustedKeyPresent: Unsupported digest %d", ds->digestType);
2784 continue;
2785 }
2786 else
2787 {
2788 debugdnssec("TrustedKeyPresent: digest type %d", ds->digestType);
2789 }
2790 for (keyv = dv->key; keyv; keyv = keyv->next)
2791 {
2792 key = (rdataDNSKey *)keyv->rdata;
2793 mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
2794 if (tag != ds->keyTag)
2795 {
2796 debugdnssec("TrustedKeyPresent:Not a valid keytag %d", tag);
2797 continue;
2798 }
2799 if (!SameDomainName(&keyv->name, &ta->zone))
2800 {
2801 debugdnssec("TrustedKeyPresent: domainame mismatch key %##s, ta %##s", keyv->name.c, ta->zone.c);
2802 continue;
2803 }
2804 return mDNStrue;
2805 }
2806 }
2807 return mDNSfalse;
2808 }
2809
2810 mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv)
2811 {
2812 mDNSu8 *digest;
2813 int digestLen;
2814 domainname name;
2815 rdataRRSig *rrsig;
2816 rdataDS *ds;
2817 rdataDNSKey *key;
2818 TrustAnchor *ta;
2819 RRVerifier *keyv;
2820 mStatus algRet;
2821 mDNSu32 currTime = mDNSPlatformUTC();
2822
2823 rrsig = (rdataRRSig *)dv->rrsig->rdata;
2824
2825 // Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies
2826 // the hash. If we find one, verify that this key was used to sign the KEY rrsets in
2827 // this zone. Loop till we find one.
2828 for (ta = m->TrustAnchors; ta; ta = ta->next)
2829 {
2830 ds = (rdataDS *)&ta->rds;
2831 if ((ds->digestType != SHA1_DIGEST_TYPE) && (ds->digestType != SHA256_DIGEST_TYPE))
2832 {
2833 LogMsg("TrustedKey: Unsupported digest %d", ds->digestType);
2834 continue;
2835 }
2836 else
2837 {
2838 debugdnssec("TrustedKey: Zone %##s, digest type %d, tag %d", ta->zone.c, ds->digestType, ds->keyTag);
2839 }
2840 for (keyv = dv->key; keyv; keyv = keyv->next)
2841 {
2842 key = (rdataDNSKey *)keyv->rdata;
2843 mDNSu16 tag = (mDNSu16)keytag((mDNSu8 *)key, keyv->rdlength);
2844 if (tag != ds->keyTag)
2845 {
2846 debugdnssec("TrustedKey:Not a valid keytag %d", tag);
2847 continue;
2848 }
2849 if (!SameDomainName(&keyv->name, &ta->zone))
2850 {
2851 debugdnssec("TrustedKey: domainame mismatch key %##s, ta %##s", keyv->name.c, ta->zone.c);
2852 continue;
2853 }
2854 if (DNS_SERIAL_LT(ta->validUntil, currTime))
2855 {
2856 LogDNSSEC("TrustedKey: Expired: currentTime %d, ExpireTime %d", (int)currTime, ta->validUntil);
2857 continue;
2858 }
2859 if (DNS_SERIAL_LT(currTime, ta->validFrom))
2860 {
2861 LogDNSSEC("TrustedKey: Future: currentTime %d, InceptTime %d", (int)currTime, ta->validFrom);
2862 continue;
2863 }
2864
2865 if (DNSNameToLowerCase((domainname *)&rrsig->signerName, &name) != mStatus_NoError)
2866 {
2867 LogMsg("TrustedKey: ERROR!! cannot convert to lower case");
2868 continue;
2869 }
2870
2871 if (dv->ctx) AlgDestroy(dv->ctx);
2872 dv->ctx = AlgCreate(DIGEST_ALG, ds->digestType);
2873 if (!dv->ctx)
2874 {
2875 LogMsg("TrustedKey: ERROR!! No digest support");
2876 continue;
2877 }
2878 digest = ds->digest;
2879 digestLen = ta->digestLen;
2880
2881 AlgAdd(dv->ctx, name.c, DomainNameLength(&name));
2882 AlgAdd(dv->ctx, key, keyv->rdlength);
2883
2884 algRet = AlgVerify(dv->ctx, mDNSNULL, 0, digest, digestLen);
2885 AlgDestroy(dv->ctx);
2886 dv->ctx = mDNSNULL;
2887 if (algRet == mStatus_NoError)
2888 {
2889 LogDNSSEC("TrustedKey: DS Validated Successfully, need to verify the key %d", tag);
2890 // We found the DNS KEY that is authenticated by the DS in our parent zone. Check to see if this key
2891 // was used to sign the DNS KEY RRSET. If so, then the keys in our DNS KEY RRSET are valid
2892 if (ValidateSignatureWithKeyForAllRRSigs(dv, dv->key, keyv, dv->rrsigKey))
2893 {
2894 LogDNSSEC("TrustedKey: DS Validated Successfully %d", tag);
2895 return mStatus_NoError;
2896 }
2897 }
2898 }
2899 }
2900 return mStatus_NoSuchRecord;
2901 }
2902
2903 mDNSlocal CacheRecord* NegativeCacheRecordForRR(mDNS *const m, const ResourceRecord *const rr)
2904 {
2905 mDNSu32 slot;
2906 mDNSu32 namehash;
2907 CacheGroup *cg;
2908 CacheRecord *cr;
2909
2910 slot = HashSlot(rr->name);
2911 namehash = DomainNameHashValue(rr->name);
2912 cg = CacheGroupForName(m, slot, namehash, rr->name);
2913 if (!cg)
2914 {
2915 LogMsg("NegativeCacheRecordForRR: cg null %##s", rr->name->c);
2916 return mDNSNULL;
2917 }
2918 for (cr=cg->members; cr; cr=cr->next)
2919 {
2920 if (cr->resrec.RecordType == kDNSRecordTypePacketNegative && (&cr->resrec == rr))
2921 return cr;
2922 }
2923 return mDNSNULL;
2924 }
2925
2926 mDNSlocal void VerifySigCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2927 {
2928 DNSSECVerifier *dv = (DNSSECVerifier *)question->QuestionContext;
2929 mDNSu16 rrtype;
2930 CacheRecord *negcr;
2931
2932 debugdnssec("VerifySigCallback: AddRecord %d, dv %p", AddRecord, dv);
2933
2934 if (!AddRecord) return;
2935
2936 LogDNSSEC("VerifySigCallback: Called with record %s", RRDisplayString(m, answer));
2937
2938 mDNS_Lock(m);
2939 if ((m->timenow - question->StopTime) >= 0)
2940 {
2941 mDNS_Unlock(m);
2942 LogDNSSEC("VerifySigCallback: Question %##s (%s) timed out", question->qname.c, DNSTypeName(question->qtype));
2943 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2944 return;
2945 }
2946 mDNS_Unlock(m);
2947
2948 if (answer->RecordType == kDNSRecordTypePacketNegative)
2949 {
2950 CacheRecord *cr;
2951 LogDNSSEC("VerifySigCallback: Received a negative answer with record %s, AddRecord %d",
2952 RRDisplayString(m, answer), AddRecord);
2953 cr = NegativeCacheRecordForRR(m, answer);
2954 if (cr && cr->nsec)
2955 {
2956 dv->DVCallback = DNSSECNegativeValidationCB;
2957 ValidateWithNSECS(m, dv, cr);
2958 }
2959 else
2960 {
2961 LogDNSSEC("VerifySigCallback: Missing record (%s) Negative Cache Record %p", RRDisplayString(m, answer), cr);
2962 dv->DVCallback(m, dv, DNSSEC_Bogus);
2963 }
2964 return;
2965 }
2966
2967 if (!dv->rrset)
2968 {
2969 LogMsg("VerifySigCallback: ERROR!! rrset NULL");
2970 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
2971 return;
2972 }
2973
2974 rrtype = answer->rrtype;
2975 // Check whether we got any answers for the question. If there are no answers, we
2976 // can't do the verification.
2977 //
2978 // We need to look at the whole rrset for verifying the signatures. This callback gets
2979 // called back for each record in the rrset sequentially and we won't know when to start the
2980 // verification. Hence, we look for all the records in the rrset ourselves using the
2981 // CheckXXX function below. The caller has to ensure that all the records in the rrset are
2982 // added to the cache before calling this callback which happens naturally because all
2983 // unicast records are marked for DelayDelivery and hence added to the cache before the
2984 // callback is done.
2985 //
2986 // We also need the RRSIGs for the rrset to do the validation. It is possible that the
2987 // cache contains RRSIG records but it may not be a valid record when we filter them
2988 // in CheckXXX function. For example, some application can query for RRSIG records which
2989 // might come back with a partial set of RRSIG records from the recursive server and
2990 // they may not be the right ones for the current validation. In this case, we still
2991 // need to send the query out to get the right RRSIGs but the "core" should not answer
2992 // this query with the same records that we checked and found them to be unusable.
2993 //
2994 // We handle this in two ways:
2995 //
2996 // 1) AnswerNewQuestion always sends the "ValidatingResponse" query out bypassing the cache.
2997 //
2998 // 2) DNSSECRecordAnswersQuestion does not answer a question with RRSIGs matching the
2999 // same name as the query until the typeCovered also matches the query's type.
3000 //
3001 // NOTE: We use "next - 1" as next always points to what we are going to fetch next and not the one
3002 // we are fetching currently
3003 switch(dv->next - 1)
3004 {
3005 case RRVS_rr:
3006 // Verification always starts at RRVS_rrsig (which means dv->next points at RRVS_key) as verification does
3007 // not begin until we have the main rrset.
3008 LogDNSSEC("VerifySigCallback: ERROR!! rrset %##s dv->next is RRVS_rr", dv->rrset->name.c);
3009 return;
3010 case RRVS_rrsig:
3011 // We can get called back with rrtype matching qtype as new records are added to the cache
3012 // triggered by other questions. This could potentially mean that the rrset that is being
3013 // validated by this "dv" whose rrsets were initialized at the beginning of the verification
3014 // may not be the right one. If this case happens, we will detect this at the end of validation
3015 // and throw away the validation results. This should not be a common case.
3016 if (rrtype != kDNSType_RRSIG)
3017 {
3018 LogDNSSEC("VerifySigCallback: RRVS_rrsig called with %s", RRDisplayString(m, answer));
3019 return;
3020 }
3021 if (CheckRRSIGForRRSet(m, dv, &negcr) != mStatus_NoError)
3022 {
3023 LogDNSSEC("VerifySigCallback: Unable to find RRSIG for %##s (%s), question %##s", dv->rrset->name.c,
3024 DNSTypeName(dv->rrset->rrtype), question->qname.c);
3025 dv->DVCallback(m, dv, DNSSEC_Bogus);
3026 return;
3027 }
3028 break;
3029 case RRVS_key:
3030 // We are waiting for the DNSKEY record and hence dv->key should be NULL. If RRSIGs are being
3031 // returned first, ignore them for now.
3032 if (dv->key)
3033 LogDNSSEC("VerifySigCallback: ERROR!! RRVS_key dv->key non-NULL for %##s", question->qname.c);
3034 if (rrtype == kDNSType_RRSIG)
3035 {
3036 LogDNSSEC("VerifySigCallback: RRVS_key rrset type %s, %##s received before DNSKEY", DNSTypeName(rrtype), question->qname.c);
3037 return;
3038 }
3039 if (rrtype != question->qtype)
3040 {
3041 LogDNSSEC("VerifySigCallback: ERROR!! RRVS_key rrset type %s, %##s not matching qtype %d", DNSTypeName(rrtype), question->qname.c,
3042 question->qtype);
3043 return;
3044 }
3045 if (CheckKeyForRRSIG(m, dv, &negcr) != mStatus_NoError)
3046 {
3047 LogDNSSEC("VerifySigCallback: Unable to find DNSKEY for %##s (%s), question %##s", dv->rrset->name.c,
3048 DNSTypeName(dv->rrset->rrtype), question->qname.c);
3049 dv->DVCallback(m, dv, DNSSEC_Indeterminate);
3050 return;
3051 }
3052 break;
3053 case RRVS_rrsig_key:
3054 // If we are in RRVS_rrsig_key, it means that we already found the relevant DNSKEYs (dv->key should be non-NULL).
3055 // If DNSKEY record is being returned i.e., it means it is being added to the cache, then it can't be in our
3056 // list.
3057 if (!dv->key)
3058 LogDNSSEC("VerifySigCallback: ERROR!! RRVS_rrsig_key dv->key NULL for %##s", question->qname.c);
3059 if (rrtype == question->qtype)
3060 {
3061 LogDNSSEC("VerifySigCallback: RRVS_rrsig_key rrset type %s, %##s", DNSTypeName(rrtype), question->qname.c);
3062 CheckOneKeyForRRSIG(dv, answer);
3063 return;
3064 }
3065 if (rrtype != kDNSType_RRSIG)
3066 {
3067 LogDNSSEC("VerifySigCallback: RRVS_rrsig_key rrset type %s, %##s not matching qtype %d", DNSTypeName(rrtype), question->qname.c,
3068 question->qtype);
3069 return;
3070 }
3071 if (CheckRRSIGForKey(m, dv, &negcr) != mStatus_NoError)
3072 {
3073 LogDNSSEC("VerifySigCallback: Unable to find RRSIG for %##s (%s), question %##s", dv->rrset->name.c,
3074 DNSTypeName(dv->rrset->rrtype), question->qname.c);
3075 dv->DVCallback(m, dv, DNSSEC_Bogus);
3076 return;
3077 }
3078 break;
3079 case RRVS_ds:
3080 if (rrtype == question->qtype)
3081 {
3082 LogDNSSEC("VerifySigCallback: RRVS_ds rrset type %s, %##s", DNSTypeName(rrtype), question->qname.c);
3083 }
3084 else
3085 {
3086 LogDNSSEC("VerifySigCallback: RRVS_ds rrset type %s, %##s received before DS", DNSTypeName(rrtype), question->qname.c);
3087 }
3088 // It is not an error if we don't find the DS record as we could have
3089 // a trusted key. Or this is not a secure delegation which will be handled
3090 // below.
3091 if (CheckDSForKey(m, dv, &negcr) != mStatus_NoError)
3092 {
3093 LogDNSSEC("VerifySigCallback: Unable find DS for %##s (%s), question %##s", dv->rrset->name.c,
3094 DNSTypeName(dv->rrset->rrtype), question->qname.c);
3095 }
3096 // dv->next is already at RRVS_done, so if we "break" from here, we will end up
3097 // in FinishDNSSECVerification. We should not do that if we receive a negative
3098 // response. For all other cases above, GetAllRRSetsForVerification handles
3099 // negative cache record
3100 if (negcr)
3101 {
3102 if (!negcr->nsec)
3103 {
3104 LogDNSSEC("VerifySigCallback: No nsec records for %##s (DS)", dv->ds->name.c);
3105 dv->DVCallback(m, dv, DNSSEC_Bogus);
3106 return;
3107 }
3108 dv->DVCallback = DNSSECNegativeValidationCB;
3109 ValidateWithNSECS(m, dv, negcr);
3110 return;
3111 }
3112 break;
3113 default:
3114 LogDNSSEC("VerifySigCallback: ERROR!! default case rrset %##s question %##s", dv->rrset->name.c, question->qname.c);
3115 dv->DVCallback(m, dv, DNSSEC_Bogus);
3116 return;
3117 }
3118 if (dv->next != RRVS_done)
3119 {
3120 mDNSBool done = GetAllRRSetsForVerification(m, dv);
3121 if (done)
3122 {
3123 if (dv->next != RRVS_done)
3124 LogMsg("VerifySigCallback ERROR!! dv->next is not done");
3125 else
3126 LogDNSSEC("VerifySigCallback: all rdata sets available for sig verification");
3127 }
3128 else
3129 {
3130 LogDNSSEC("VerifySigCallback: all rdata sets not available for sig verification");
3131 return;
3132 }
3133 }
3134 FinishDNSSECVerification(m, dv);
3135 }