@@ -90,6 +90,34 @@ public ValUtils() {
90
90
this .verifier = new DnsSecVerifier ();
91
91
}
92
92
93
+ /**
94
+ * Set the owner name of NSEC RRsets to the canonical name, i.e. the name
95
+ * that is <b>not</b> expanded from a wildcard label.
96
+ * @param set The RRset to canonicalize.
97
+ * @param sig The signature that validated this RRset.
98
+ */
99
+ public static void setCanonicalNsecOwner (SRRset set , RRSIGRecord sig ) {
100
+ if (set .getType () != Type .NSEC ) {
101
+ return ;
102
+ }
103
+
104
+ Record nsec = set .first ();
105
+ int fqdnLabelCount = nsec .getName ().labels () - 1 ; // don't count the root label
106
+ if (nsec .getName ().isWild ()) {
107
+ --fqdnLabelCount ; // don't count the wildcard label
108
+ }
109
+
110
+ if (sig .getLabels () == fqdnLabelCount ) {
111
+ set .setName (nsec .getName ());
112
+ }
113
+ else if (sig .getLabels () < fqdnLabelCount ) {
114
+ set .setName (nsec .getName ().wild (sig .getSigner ().labels () - sig .getLabels ()));
115
+ }
116
+ else {
117
+ throw new IllegalArgumentException ("invalid nsec record" );
118
+ }
119
+ }
120
+
93
121
/**
94
122
* Initialize the module. The recognized configuration value are
95
123
* <ul>
@@ -445,13 +473,14 @@ public static boolean strictSubdomain(Name domain1, Name domain2) {
445
473
* {@link NSECRecord#getNext()}).
446
474
*
447
475
* @param domain The name for which the closest encloser is queried.
448
- * @param nsec The covering {@link NSECRecord} to check.
476
+ * @param owner The beginning of the covering {@link Name} to check.
477
+ * @param next The end of the covering {@link Name} to check.
449
478
* @return The closest encloser name of <code>domain</code> as defined by
450
- * < code>nsec</ code> .
479
+ * {@ code owner} and {@ code next} .
451
480
*/
452
- public static Name closestEncloser (Name domain , NSECRecord nsec ) {
453
- Name n1 = longestCommonName (domain , nsec . getName () );
454
- Name n2 = longestCommonName (domain , nsec . getNext () );
481
+ public static Name closestEncloser (Name domain , Name owner , Name next ) {
482
+ Name n1 = longestCommonName (domain , owner );
483
+ Name n2 = longestCommonName (domain , next );
455
484
456
485
return (n1 .labels () > n2 .labels ()) ? n1 : n2 ;
457
486
}
@@ -462,28 +491,29 @@ public static Name closestEncloser(Name domain, NSECRecord nsec) {
462
491
*
463
492
* @param domain The name for which the wildcard closest encloser is
464
493
* demanded.
494
+ * @param set The RRset containing {@code nsec} to check.
465
495
* @param nsec The covering NSEC that defines the encloser.
466
496
* @return The wildcard closest encloser name of <code>domain</code> as
467
497
* defined by <code>nsec</code>.
468
498
* @throws NameTooLongException If adding the wildcard label to the closest
469
499
* encloser results in an invalid name.
470
500
*/
471
- public static Name nsecWildcard (Name domain , NSECRecord nsec ) throws NameTooLongException {
472
- Name origin = closestEncloser (domain , nsec );
501
+ public static Name nsecWildcard (Name domain , SRRset set , NSECRecord nsec ) throws NameTooLongException {
502
+ Name origin = closestEncloser (domain , set . getName (), nsec . getNext () );
473
503
return Name .concatenate (WILDCARD , origin );
474
504
}
475
505
476
506
/**
477
507
* Determine if the given NSEC proves a NameError (NXDOMAIN) for a given
478
508
* qname.
479
509
*
510
+ * @param set The RRset that contains the NSEC.
480
511
* @param nsec The NSEC to check.
481
512
* @param qname The qname to check against.
482
- * @param signerName The signer of the NSEC RRset.
483
513
* @return true if the NSEC proves the condition.
484
514
*/
485
- public static boolean nsecProvesNameError (NSECRecord nsec , Name qname , Name signerName ) {
486
- Name owner = nsec .getName ();
515
+ public static boolean nsecProvesNameError (SRRset set , NSECRecord nsec , Name qname ) {
516
+ Name owner = set .getName ();
487
517
Name next = nsec .getNext ();
488
518
489
519
// If NSEC owner == qname, then this NSEC proves that qname exists.
@@ -492,7 +522,7 @@ public static boolean nsecProvesNameError(NSECRecord nsec, Name qname, Name sign
492
522
}
493
523
494
524
// deny overreaching NSECs
495
- if (!next .subdomain (signerName )) {
525
+ if (!next .subdomain (set . getSignerName () )) {
496
526
return false ;
497
527
}
498
528
@@ -539,29 +569,25 @@ else if (owner.compareTo(next) > 0) {
539
569
* Determine if a NSEC record proves the non-existence of a wildcard that
540
570
* could have produced qname.
541
571
*
542
- * @param nsec The nsec to check.
572
+ * @param set The RRset of the NSEC record.
573
+ * @param nsec The nsec record to check.
543
574
* @param qname The qname to check against.
544
- * @param signerName The signer of the NSEC RRset.
545
575
* @return true if the NSEC proves the condition.
546
576
*/
547
- public static boolean nsecProvesNoWC (NSECRecord nsec , Name qname , Name signerName ) {
548
- int qnameLabels = qname .labels ();
549
- Name ce = closestEncloser (qname , nsec );
550
- int ceLabels = ce .labels ();
551
-
552
- for (int i = qnameLabels - ceLabels ; i > 0 ; i --) {
553
- Name wcName = qname .wild (i );
554
- if (nsecProvesNameError (nsec , wcName , signerName )) {
555
- return true ;
556
- }
577
+ public static boolean nsecProvesNoWC (SRRset set , NSECRecord nsec , Name qname ) {
578
+ Name ce = closestEncloser (qname , set .getName (), nsec .getNext ());
579
+ int labelsToStrip = qname .labels () - ce .labels ();
580
+ if (labelsToStrip > 0 ) {
581
+ Name wcName = qname .wild (labelsToStrip );
582
+ return nsecProvesNameError (set , nsec , wcName );
557
583
}
558
584
559
585
return false ;
560
586
}
561
587
562
588
/**
563
589
* Container for responses of
564
- * {@link ValUtils#nsecProvesNodata(NSECRecord, Name, int)}.
590
+ * {@link ValUtils#nsecProvesNodata(SRRset, NSECRecord, Name, int)}.
565
591
*/
566
592
public static class NsecProvesNodataResponse {
567
593
boolean result ;
@@ -575,22 +601,23 @@ public static class NsecProvesNodataResponse {
575
601
* must still be provided proof that qname did not directly exist and that
576
602
* the wildcard is, in fact, *.closest_encloser.
577
603
*
604
+ * @param set The RRset of the NSEC record.
578
605
* @param nsec The NSEC to check
579
606
* @param qname The query name to check against.
580
607
* @param qtype The query type to check against.
581
608
* @return true if the NSEC proves the condition.
582
609
*/
583
- public static NsecProvesNodataResponse nsecProvesNodata (NSECRecord nsec , Name qname , int qtype ) {
610
+ public static NsecProvesNodataResponse nsecProvesNodata (SRRset set , NSECRecord nsec , Name qname , int qtype ) {
584
611
NsecProvesNodataResponse result = new NsecProvesNodataResponse ();
585
- if (!nsec .getName ().equals (qname )) {
612
+ if (!set .getName ().equals (qname )) {
586
613
// empty-non-terminal checking.
587
614
// Done before wildcard, because this is an exact match,
588
615
// and would prevent a wildcard from matching.
589
616
590
617
// If the nsec is proving that qname is an ENT, the nsec owner will
591
618
// be less than qname, and the next name will be a child domain of
592
619
// the qname.
593
- if (strictSubdomain (nsec .getNext (), qname ) && nsec .getName ().compareTo (qname ) < 0 ) {
620
+ if (strictSubdomain (nsec .getNext (), qname ) && set .getName ().compareTo (qname ) < 0 ) {
594
621
result .result = true ;
595
622
return result ;
596
623
}
@@ -600,9 +627,9 @@ public static NsecProvesNodataResponse nsecProvesNodata(NSECRecord nsec, Name qn
600
627
// have generated qname from the wildcard and b) the type map does
601
628
// not contain qtype. Note that this does NOT prove that this
602
629
// wildcard was the applicable wildcard.
603
- if (nsec .getName ().isWild ()) {
630
+ if (set .getName ().isWild ()) {
604
631
// the is the purported closest encloser.
605
- Name ce = new Name (nsec .getName (), 1 );
632
+ Name ce = new Name (set .getName (), 1 );
606
633
607
634
// The qname must be a strict subdomain of the closest encloser,
608
635
// and the qtype must be absent from the type map.
@@ -720,16 +747,16 @@ public JustifiedSecStatus nsecProvesNodataDsReply(Message request, SMessage resp
720
747
}
721
748
722
749
NSECRecord nsec = (NSECRecord )set .first ();
723
- ndp = ValUtils .nsecProvesNodata (nsec , qname , Type .DS );
750
+ ndp = ValUtils .nsecProvesNodata (set , nsec , qname , Type .DS );
724
751
if (ndp .result ) {
725
752
hasValidNSEC = true ;
726
753
if (ndp .wc != null && nsec .getName ().isWild ()) {
727
754
wcNsec = nsec ;
728
755
}
729
756
}
730
757
731
- if (ValUtils .nsecProvesNameError (nsec , qname , set . getSignerName () )) {
732
- ce = closestEncloser (qname , nsec );
758
+ if (ValUtils .nsecProvesNameError (set , nsec , qname )) {
759
+ ce = closestEncloser (qname , set . getName (), nsec . getNext () );
733
760
}
734
761
}
735
762
0 commit comments