diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nickserver.rb | 5 | ||||
-rw-r--r-- | lib/nickserver/hkp/fetch_key_info.rb | 56 | ||||
-rw-r--r-- | lib/nickserver/hkp/parse_key_info.rb | 93 |
3 files changed, 102 insertions, 52 deletions
diff --git a/lib/nickserver.rb b/lib/nickserver.rb index 951dae9..eb7eddb 100644 --- a/lib/nickserver.rb +++ b/lib/nickserver.rb @@ -5,9 +5,10 @@ require "nickserver/email_address" require "nickserver/couch/fetch_key" -require "nickserver/hkp/key_info" -require "nickserver/hkp/fetch_key_info" require "nickserver/hkp/fetch_key" +require "nickserver/hkp/fetch_key_info" +require "nickserver/hkp/parse_key_info" +require "nickserver/hkp/key_info" require "nickserver/server" require "nickserver/daemon" diff --git a/lib/nickserver/hkp/fetch_key_info.rb b/lib/nickserver/hkp/fetch_key_info.rb index 2cfff43..bc12488 100644 --- a/lib/nickserver/hkp/fetch_key_info.rb +++ b/lib/nickserver/hkp/fetch_key_info.rb @@ -8,23 +8,16 @@ module Nickserver; module HKP class FetchKeyInfo include EM::Deferrable - # for this regexp to work, the source text must end in a trailing "\n", - # which the output of sks does. - MATCH_PUB_KEY = /(^pub:.+?\n(^uid:.+?\n)+)/m - def search(uid) # in practice, exact=on seems to have no effect params = {:op => 'vindex', :search => uid, :exact => 'on', :options => 'mr', :fingerprint => 'on'} EventMachine::HttpRequest.new(Config.hkp_url).get(:query => params).callback {|http| - if http.response_header.status != 200 - self.fail http.response_header.status, "Could net fetch keyinfo." + parser = ParseKeyInfo.new http.response_header, http.response + keys = parser.keys(uid) + if keys.any? + self.succeed keys else - keys, errors = parse(uid, http.response) - if keys.empty? - self.fail 500, errors.join("\n") - else - self.succeed keys - end + self.fail parser.status(uid), parser.msg(uid) end }.errback {|http| self.fail 500, http.error @@ -32,43 +25,6 @@ module Nickserver; module HKP self end - # - # input: - # uid -- uid to search for - # vindex_result -- raw output from a vindex hkp query (machine readable) - # - # returns: - # an array of: - # [0] -- array of eligible keys (as HKPKeyInfo objects) matching uid. - # [1] -- array of error messages - # - # keys are eliminated from eligibility for a number of reasons, including expiration, - # revocation, uid match, key length, and so on... - # - def parse(uid, vindex_result) - keys = [] - errors = [] - now = Time.now - vindex_result.scan(MATCH_PUB_KEY).each do |match| - key_info = KeyInfo.new(match[0]) - if key_info.uids.include?(uid) - if key_info.keylen < 2048 - errors << "Ignoring key #{key_info.keyid} for #{uid}: key length is too short." - elsif key_info.expired? - errors << "Ignoring key #{key_info.keyid} for #{uid}: key expired." - elsif key_info.revoked? - errors << "Ignoring key #{key_info.keyid} for #{uid}: key revoked." - elsif key_info.disabled? - errors << "Ignoring key #{key_info.keyid} for #{uid}: key disabled." - elsif key_info.expirationdate && key_info.expirationdate < now - errors << "Ignoring key #{key_info.keyid} for #{uid}: key expired" - else - keys << key_info - end - end - end - [keys, errors] - end end -end; end
\ No newline at end of file +end; end diff --git a/lib/nickserver/hkp/parse_key_info.rb b/lib/nickserver/hkp/parse_key_info.rb new file mode 100644 index 0000000..2bfcb7e --- /dev/null +++ b/lib/nickserver/hkp/parse_key_info.rb @@ -0,0 +1,93 @@ +module Nickserver; module HKP + class ParseKeyInfo + + # for this regexp to work, the source text must end in a trailing "\n", + # which the output of sks does. + MATCH_PUB_KEY = /(^pub:.+?\n(^uid:.+?\n)+)/m + + # header -- header of the hkp response + # vindex_result -- raw output from a vindex hkp query (machine readable) + def initialize(header, vindex_result) + @header = header + @vindex_result = vindex_result + end + + def status(uid) + if header.status == 200 && keys(uid).any? + 200 + else + error_status(uid) + end + end + + def keys(uid) + key_infos(uid).reject { |key| error_for_key(key) } + end + + def msg(uid) + if errors(uid).any? + error_messages(uid).join "\n" + else + "Could not fetch keyinfo." + end + end + + protected + + attr_reader :header + attr_reader :vindex_result + + def error_status(uid) + if header.status != 200 + header.status + else + if errors(uid).any? + 500 + else + 404 + end + end + end + + def errors(uid) + key_infos(uid).map{|key| error_for_key(key) }.compact + end + + def error_messages(uid) + key_infos(uid).map do |key| + err = error_for_key(key) + error_message(uid, key, err) + end.compact + end + + def key_infos(uid) + all_key_infos.select do |key_info| + key_info.uids.include?(uid) + end + end + + def all_key_infos + @all_key_infos ||= vindex_result.scan(MATCH_PUB_KEY).map do |match| + KeyInfo.new(match[0]) + end + end + + def error_message(uid, key, err) + "Ignoring key #{key.keyid} for #{uid}: #{err}" if err + end + + def error_for_key(key) + if key.keylen < 2048 + "key length is too short." + elsif key.expired? + "key expired." + elsif key.revoked? + "key revoked." + elsif key.disabled? + "key disabled." + elsif key.expirationdate && key.expirationdate < Time.now + "key expired" + end + end + end +end; end |