1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
#--
#Copyright 2007 Nominet UK
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#++
module Dnsruby
# Takes care of the validation for the SelectThread. If queries need to be
# made in order to validate the response, then a separate thread is fired up
# to do this.
class ValidatorThread # :nodoc: all
# include Singleton
def initialize(*args)
@client_id, @client_queue, @response, @error, @query, @st, @res = args
# Create the validation thread, and a queue to receive validation requests
# Actually, need to have a thread per validator, as they make recursive calls.
# @@mutex = Mutex.new
# @@validation_queue = Queue.new
# @@validator_thread = Thread.new{
# do_validate
# }
end
def run
# ONLY START THE NEW THREAD IF VALIDATION NEED OCCUR!!
if (should_validate)
Thread.new{
do_validate
}
else
do_validate
end
end
# def add_to_queue(item)
# print "ADding to validator queue\n"
## @@mutex.synchronize{
# @@validation_queue.push(item)
## }
# end
def do_validate
# while (true)
# item = nil
# print "Waiting to pop validation item\n"
## @@mutex.synchronize{
# item = @@validation_queue.pop
## }
# print "Popped validation request\n"
# client_id, client_queue, response, err, query, st, res = item
validated_ok = validate(@query, @response, @res)
validated_ok = false if (@error && !(NXDomain === @error))
cache_if_valid(@query, @response)
# Now send the response back to the client...
# print "#{Time.now} : Got result for #{@query.question()[0].qname}, #{@query.question()[0].qtype}\n"
if (validated_ok)
@st.push_validation_response_to_select(@client_id, @client_queue, @response, nil, @query, @res)
else
@st.push_validation_response_to_select(@client_id, @client_queue, @response,
@response.security_error, @query, @res)
end
# end
end
def should_validate
return ValidatorThread.requires_validation?(@query, @response, @error, @res)
end
def ValidatorThread.requires_validation?(query, response, error, res)
# @error will be nil for DNS RCODE errors - it will be true for TsigError. really?!
if ((!error || (error.instance_of?NXDomain)) && query.do_validation)
if (res.dnssec)
if (response.security_level != Message::SecurityLevel::SECURE)
return true
end
end
end
return false
end
def validate(query, response, res)
if (should_validate)
begin
# So, we really need to be able to take the response out of the select thread, along
# with the responsibility for sending the answer to the client.
# Should we have a validator thread? Or a thread per validation?
# Then, select thread gets response. It performs basic checks here.
# After basic checks, the select-thread punts the response (along with queues, etc.)
# to the validator thread.
# The validator validates it (or just releases it with no validation), and then
# sends the request to the client via the client queue.
Dnssec.validate_with_query(query,response)
return true
rescue VerifyError => e
response.security_error = e
# Response security_level should already be set
return false
end
end
return true
end
def cache_if_valid(query, response)
return if @error
PacketSender.cache(query, response)
end
end
end
|