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
|
require 'em-http'
#
# used to fetch an array of KeyInfo objects that match the given uid.
#
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."
else
keys, errors = parse(uid, http.response)
if keys.empty?
self.fail 500, errors.join("\n")
else
self.succeed keys
end
end
}.errback {|http|
self.fail 500, http.error
}
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
|