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