Object
RFC4033, section 7
"There is one more step that a security-aware stub resolver can take if, for whatever reason, it is not able to establish a useful trust relationship with the recursive name servers that it uses: it can perform its own signature validation by setting the Checking Disabled (CD) bit in its query messages. A validating stub resolver is thus able to treat the DNSSEC signatures as trust relationships between the zone administrators and the stub resolver itself. "
Dnsruby is configured to validate responses by default. However, it is not configured with any trusted keys by default. Applications may use the verify() method to perform verification with of RRSets of Messages with given keys. Alternatively, trusted keys may be added to this class (either directly, or by loading the IANA TAR or the DLV ISC ZSK). Validation will then be performed from these keys (or the DLV registry, if configured). Negative and positive responses are validation.
Messages are tagged with the current security_level (Message::SecurityLevel). UNCHECKED means Dnsruby has not attempted to validate the response. BOGUS means the response has been checked, and is bogus. INSECURE means the response has been validated to be insecure (e.g. in an unsigned zone) SECURE means that the response has been verfied to be correct.
Several validators are provided, with each maintaining its own cache of trusted keys. If validators are added or removed, the caches of the other validators are not affected.
Add a trusted Key Signing Key for the ISC DLV registry.
# File lib/Dnsruby/dnssec.rb, line 92 92: def Dnssec.add_dlv_key(dlv_key) 93: @@dlv_verifier.add_dlv_key(dlv_key) 94: end
Add a new trust anchor
# File lib/Dnsruby/dnssec.rb, line 96 96: def Dnssec.add_trust_anchor(t) 97: # @TODO@ Create a new verifier? 98: @@anchor_verifier.add_trust_anchor(t) 99: end
Add the trusted key with the given expiration time
# File lib/Dnsruby/dnssec.rb, line 101 101: def self.add_trust_anchor_with_expiration(k, expiration) 102: # Create a new verifier? 103: @@anchor_verifier.add_trust_anchor_with_expiration(k, expiration) 104: end
# File lib/Dnsruby/dnssec.rb, line 289 289: def self.anchor_verifier 290: return @@anchor_verifier 291: end
Wipes the cache of trusted keys
# File lib/Dnsruby/dnssec.rb, line 110 110: def self.clear_trust_anchors 111: @@anchor_verifier.clear_trust_anchors 112: end
# File lib/Dnsruby/dnssec.rb, line 118 118: def self.clear_trusted_keys 119: [@@anchor_verifier, @@root_verifier, @@dlv_verifier].each {|v| 120: v.clear_trusted_keys 121: } 122: end
# File lib/Dnsruby/dnssec.rb, line 167 167: def self.default_resolver 168: return @@default_resolver 169: end
This method overrides the system default resolver configuration for validation If default_resolver is set, then it will be used to follow the chain of trust. If it is not, then the default system resolver will be used (unless do_validation_with_recursor is set.
# File lib/Dnsruby/dnssec.rb, line 164 164: def self.default_resolver=(res) 165: @@default_resolver = res 166: end
# File lib/Dnsruby/dnssec.rb, line 292 292: def self.dlv_verifier 293: return @@dlv_verifier 294: end
This method defines the choice of Resolver or Recursor, when the validator is checking responses. If set to true, then a Recursor will be used to query for the DNSSEC records. Otherwise, the default system resolver will be used.
# File lib/Dnsruby/dnssec.rb, line 154 154: def self.do_validation_with_recursor(on) 155: @@do_validation_with_recursor = on 156: end
# File lib/Dnsruby/dnssec.rb, line 157 157: def self.do_validation_with_recursor? 158: return @@do_validation_with_recursor 159: end
# File lib/Dnsruby/dnssec.rb, line 137 137: def self.no_keys? 138: no_keys = true 139: [@@anchor_verifier, @@root_verifier, @@dlv_verifier].each {|v| 140: if (v.trusted_keys.length() > 0 || 141: v.trust_anchors.length() > 0) 142: no_keys = false 143: end 144: } 145: return no_keys 146: end
Remove the trusted key
# File lib/Dnsruby/dnssec.rb, line 106 106: def Dnssec.remove_trust_anchor(t) 107: @@anchor_verifier.remove_trust_anchor(t) 108: end
# File lib/Dnsruby/dnssec.rb, line 124 124: def self.reset 125: @@validation_policy = ValidationPolicy::LOCAL_ANCHORS_THEN_ROOT 126: @@root_verifier = SingleVerifier.new(SingleVerifier::VerifierType::ROOT) 127: @@root_verifier.add_root_ds(@@root_key) 128: 129: @@dlv_verifier = SingleVerifier.new(SingleVerifier::VerifierType::DLV) 130: 131: # @TODO@ Could add a new one of these for each anchor. 132: @@anchor_verifier = SingleVerifier.new(SingleVerifier::VerifierType::ANCHOR) 133: @@do_validation_with_recursor = true # Many nameservers don't handle DNSSEC correctly yet 134: @@default_resolver = Resolver.new 135: end
# File lib/Dnsruby/dnssec.rb, line 295 295: def self.root_verifier 296: return @@root_verifier 297: end
# File lib/Dnsruby/dnssec.rb, line 114 114: def self.trust_anchors 115: return @@anchor_verifier.trust_anchors 116: end
Returns true for secure/insecure, false otherwise This method will set the security_level on msg to the appropriate value. Could be : secure, insecure, bogus or indeterminate If an error is encountered during verification, then the thrown exception will define the error.
# File lib/Dnsruby/dnssec.rb, line 176 176: def self.validate(msg) 177: query = Message.new() 178: query.header.cd=true 179: return self.validate_with_query(query, msg) 180: end
# File lib/Dnsruby/dnssec.rb, line 265 265: def self.validate_with_anchors(msg, query) 266: return @@anchor_verifier.validate(msg, query) 267: end
# File lib/Dnsruby/dnssec.rb, line 273 273: def self.validate_with_dlv(msg, query) 274: return @@dlv_verifier.validate(msg, query) 275: end
# File lib/Dnsruby/dnssec.rb, line 182 182: def self.validate_with_query(query, msg) 183: if (!msg) 184: return false 185: end 186: # First, just check there is something to validate! 187: found_sigs = false 188: msg.each_resource {|rr| 189: if (rr.type == Types::RRSIG) 190: found_sigs = true 191: end 192: } 193: if (found_sigs) 194: begin 195: if (verify(msg)) 196: msg.security_level = Message::SecurityLevel.SECURE 197: return true 198: end 199: rescue VerifyError => e 200: msg.security_error = e 201: end 202: end 203: 204: # SHOULD ALWAYS VERIFY DNSSEC-SIGNED RESPONSES? 205: # Yes - if a trust anchor is configured. Otherwise, act on CD bit (in query) 206: TheLog.debug("Checking whether to validate, query.cd = #{query.header.cd}") 207: if (((@@validation_policy > ValidationPolicy::ALWAYS_ROOT_ONLY) && (self.trust_anchors().length > 0)) || 208: # Check query here, and validate if CD is true 209: (query.header.cd == true)) 210: TheLog.debug("Starting validation") 211: 212: # Validate! 213: # Need to think about trapping/storing exceptions and security_levels here 214: last_error = "" 215: last_level = Message::SecurityLevel.BOGUS 216: last_error_level = Message::SecurityLevel.BOGUS 217: if (@@validation_policy == ValidationPolicy::ALWAYS_LOCAL_ANCHORS_ONLY) 218: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 219: Proc.new{|m, q| validate_with_anchors(m, q)}, msg, query) 220: elsif (@@validation_policy == ValidationPolicy::ALWAYS_ROOT_ONLY) 221: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 222: Proc.new{|m, q| validate_with_root(m, q)}, msg, query) 223: elsif (@@validation_policy == ValidationPolicy::LOCAL_ANCHORS_THEN_ROOT) 224: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 225: Proc.new{|m, q| validate_with_anchors(m, q)}, msg, query) 226: if (last_level != Message::SecurityLevel.SECURE) 227: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 228: Proc.new{|m, q| validate_with_root(m, q)}, msg, query) 229: end 230: elsif (@@validation_policy == ValidationPolicy::ROOT_THEN_LOCAL_ANCHORS) 231: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 232: Proc.new{|m, q| validate_with_root(m, q)}, msg, query) 233: if (last_level != Message::SecurityLevel.SECURE) 234: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 235: Proc.new{|m, q| validate_with_anchors(m, q)}, msg, query) 236: end 237: end 238: if (last_level != Message::SecurityLevel.SECURE) 239: last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level, 240: Proc.new{|m, q| validate_with_dlv(m, q)}, msg, query) 241: end 242: # Set the message security level! 243: msg.security_level = last_level 244: msg.security_error = last_error 245: raise VerifyError.new(last_error) if (last_level < 0) 246: return (msg.security_level.code > Message::SecurityLevel::UNCHECKED) 247: end 248: msg.security_level = Message::SecurityLevel.UNCHECKED 249: return true 250: end
# File lib/Dnsruby/dnssec.rb, line 269 269: def self.validate_with_root(msg, query) 270: return @@root_verifier.validate(msg, query) 271: end
# File lib/Dnsruby/dnssec.rb, line 74 74: def Dnssec.validation_policy 75: @@validation_policy 76: end
# File lib/Dnsruby/dnssec.rb, line 68 68: def Dnssec.validation_policy=(p) 69: if ((p >= ALWAYS_ROOT_ONY) && (p <= ALWAYS_LOCAL_ANCHORS)) 70: @@validation_policy = p 71: # @TODO@ Should we be clearing the trusted keys now? 72: end 73: end
# File lib/Dnsruby/dnssec.rb, line 277 277: def self.verify(msg, keys=nil) 278: begin 279: return true if @@anchor_verifier.verify(msg, keys=nil) 280: rescue VerifyError 281: begin 282: return true if @@root_verifier.verify(msg, keys=nil) 283: rescue VerifyError 284: return true if @@dlv_verifier.verify(msg, keys=nil) # Will carry error to client 285: end 286: end 287: end
# File lib/Dnsruby/dnssec.rb, line 302 302: def self.verify_rrset(rrset, keys = nil) 303: return ((@@anchor_verifier.verify_rrset(rrset, keys) || 304: @@root_verifier.verify_rrset(rrset, keys) || 305: @@dlv_verifier.verify_rrset(rrset, keys))) 306: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.