summaryrefslogtreecommitdiff
path: root/lib/nickserver/hkp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nickserver/hkp')
-rw-r--r--lib/nickserver/hkp/client.rb36
-rw-r--r--lib/nickserver/hkp/key_info.rb100
-rw-r--r--lib/nickserver/hkp/parse_key_info.rb46
-rw-r--r--lib/nickserver/hkp/response.rb2
-rw-r--r--lib/nickserver/hkp/source.rb29
-rw-r--r--lib/nickserver/hkp/v_index_response.rb28
6 files changed, 117 insertions, 124 deletions
diff --git a/lib/nickserver/hkp/client.rb b/lib/nickserver/hkp/client.rb
index d53daad..d632a36 100644
--- a/lib/nickserver/hkp/client.rb
+++ b/lib/nickserver/hkp/client.rb
@@ -1,18 +1,16 @@
require 'nickserver/hkp'
-
-#
-# Client for the HKP protocol.
-#
-# This is not a complete implementation - only the parts we need.
-# Instantiate with an adapter that will take care of the http requests.
-#
-# For each request we yield http_status and the response content just
-# like the adapter does.
-
-
-module Nickserver; module Hkp
+require 'nickserver/config'
+
+module Nickserver::Hkp
+ #
+ # Client for the HKP protocol.
+ #
+ # This is not a complete implementation - only the parts we need.
+ # Instantiate with an adapter that will take care of the http requests.
+ #
+ # For each request we yield http_status and the response content just
+ # like the adapter does.
class Client
-
def initialize(adapter)
@adapter = adapter
end
@@ -20,7 +18,7 @@ module Nickserver; module Hkp
#
# used to fetch an array of KeyInfo objects that match the given email
#
- def get_key_infos_by_email(email, &block)
+ def get_key_infos_by_email(email)
get op: 'vindex', search: email.to_s, fingerprint: 'on'
end
@@ -28,7 +26,7 @@ module Nickserver; module Hkp
# fetches ascii armored OpenPGP public key from the keyserver
#
def get_key_by_fingerprint(fingerprint)
- get op: 'get', search: "0x" + fingerprint
+ get op: 'get', search: '0x' + fingerprint
end
protected
@@ -37,9 +35,9 @@ module Nickserver; module Hkp
def get(query)
# in practice, exact=on seems to have no effect
- query = {exact: 'on', options: 'mr'}.merge query
- response = adapter.get Config.hkp_url, query: query
- return response
+ query = { exact: 'on', options: 'mr' }.merge query
+ response = adapter.get Nickserver::Config.hkp_url, query: query
+ response
end
end
-end; end
+end
diff --git a/lib/nickserver/hkp/key_info.rb b/lib/nickserver/hkp/key_info.rb
index d4ecf10..e1a9500 100644
--- a/lib/nickserver/hkp/key_info.rb
+++ b/lib/nickserver/hkp/key_info.rb
@@ -1,70 +1,102 @@
require 'cgi'
require 'nickserver/hkp'
-#
-# Class to represent the key information result from a query to a key server
-# (but not the key itself).
-#
-# The initialize method parses the hkp 'machine readable' output.
-#
-# format definition of machine readable index output is here:
-# http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5.2
-#
module Nickserver::Hkp
+ #
+ # Class to represent the key information result from a query to a key server
+ # (but not the key itself).
+ #
+ # The initialize method parses the hkp 'machine readable' output.
+ #
+ # format definition of machine readable index output is here:
+ # http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5.2
+ #
class KeyInfo
- attr_accessor :uids, :keyid, :algo, :flags
+ attr_accessor :uids
def initialize(hkp_record)
uid_lines = hkp_record.split("\n")
pub_line = uid_lines.shift
- @keyid, @algo, @keylen_s, @creationdate_s, @expirationdate_s, @flags = pub_line.split(':')[1..-1]
- @uids = []
- uid_lines.each do |uid_line|
- uid, _creationdate, _expirationdate, _flags = uid_line.split(':')[1..-1]
- # for now, ignore the expirationdate and flags of uids. sks does return them anyway
- @uids << CGI.unescape(uid.sub(/.*<(.+)>.*/, '\1'))
+ @properties = pub_line.split(':')[1..-1]
+ @uids = extract_uids(uid_lines)
+ end
+
+ CHECKS = %i[too_short? expired? revoked? disabled? outdated?].freeze
+
+ def error
+ CHECKS.find do |check|
+ msg = check.to_s.chop.tr('_', ' ')
+ "key is #{msg}." if send(check)
end
end
+ def keyid
+ properties.first
+ end
+
+ def algo
+ properties.second
+ end
+
def keylen
- @keylen ||= @keylen_s.to_i
+ properties[2].to_i
end
def creationdate
- @creationdate ||= begin
- if @creationdate_s
- Time.at(@creationdate_s.to_i)
- end
- end
+ created = properties[3]
+ Time.at(created.to_i)
end
def expirationdate
- @expirationdate ||= begin
- if @expirationdate_s
- Time.at(@expirationdate_s.to_i)
- end
- end
+ expires = properties[4]
+ Time.at(expires.to_i)
+ end
+
+ def flags
+ properties.last
end
def rsa?
- @algo == "1"
+ algo == '1'
end
def dsa?
- @algo == "17"
+ algo == '17'
+ end
+
+ protected
+
+ attr_reader :properties
+
+ def extract_uids(uid_lines)
+ uid_lines.map do |uid_line|
+ # for now, ignore the expirationdate and flags of uids.
+ # sks does return them anyway
+ uid, _creationdate, _expirationdate, _flags = uid_line.split(':')[1..-1]
+ CGI.unescape(uid.sub(/.*<(.+)>.*/, '\1'))
+ end
+ end
+
+ # CHECKS
+
+ def too_short?
+ keylen < 2048
+ end
+
+ def expired?
+ flags =~ /e/
end
def revoked?
- @flags =~ /r/
+ flags =~ /r/
end
def disabled?
- @flags =~ /d/
+ flags =~ /d/
end
- def expired?
- @flags =~ /e/
+ def outdated?
+ expirationdate && expirationdate < Time.now
end
end
-
end
diff --git a/lib/nickserver/hkp/parse_key_info.rb b/lib/nickserver/hkp/parse_key_info.rb
index 2f928a0..a6f170c 100644
--- a/lib/nickserver/hkp/parse_key_info.rb
+++ b/lib/nickserver/hkp/parse_key_info.rb
@@ -1,13 +1,12 @@
-#
-# Simple parser for Hkp KeyInfo responses.
-#
-# Focus is on simple here. Trying to avoid state and sideeffects.
-# Parsing a response with 12 keys and validating them takes 2ms.
-# So no need for memoization and making things more complex.
-#
-module Nickserver; module Hkp
+module Nickserver::Hkp
+ #
+ # Simple parser for Hkp KeyInfo responses.
+ #
+ # Focus is on simple here. Trying to avoid state and sideeffects.
+ # Parsing a response with 12 keys and validating them takes 2ms.
+ # So no need for memoization and making things more complex.
+ #
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
@@ -40,14 +39,14 @@ module Nickserver; module Hkp
protected
def keys(uid)
- key_infos(uid).reject { |key| error_for_key(key) }
+ key_infos(uid).reject(&:error)
end
def msg(uid)
if errors(uid).any?
error_messages(uid).join "\n"
else
- "Could not fetch keyinfo."
+ 'Could not fetch keyinfo.'
end
end
@@ -63,13 +62,12 @@ module Nickserver; module Hkp
end
def errors(uid)
- key_infos(uid).map{|key| error_for_key(key) }.compact
+ key_infos(uid).map(&:error).compact
end
def error_messages(uid)
key_infos(uid).map do |key|
- err = error_for_key(key)
- error_message(uid, key, err)
+ error_message(uid, key)
end.compact
end
@@ -91,22 +89,8 @@ module Nickserver; module Hkp
status == 200
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
+ def error_message(uid, key)
+ "Ignoring key #{key.keyid} for #{uid}: #{key.error}" if key.error
end
end
-end; end
+end
diff --git a/lib/nickserver/hkp/response.rb b/lib/nickserver/hkp/response.rb
index c52e25f..2cc69d3 100644
--- a/lib/nickserver/hkp/response.rb
+++ b/lib/nickserver/hkp/response.rb
@@ -1,6 +1,5 @@
module Nickserver::Hkp
class Response
-
attr_reader :status, :content
def initialize(uid, key)
@@ -13,6 +12,5 @@ module Nickserver::Hkp
def format_response(map)
map.to_json
end
-
end
end
diff --git a/lib/nickserver/hkp/source.rb b/lib/nickserver/hkp/source.rb
index 82c94a0..d7c86a3 100644
--- a/lib/nickserver/hkp/source.rb
+++ b/lib/nickserver/hkp/source.rb
@@ -2,24 +2,21 @@ require 'nickserver/source'
require 'nickserver/response'
require 'nickserver/hkp/response'
require 'nickserver/hkp/client'
-require "nickserver/hkp/parse_key_info"
-require "nickserver/hkp/key_info"
-
-
-#
-# Fetch keys via HKP
-# http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
-#
-
-module Nickserver; module Hkp
+require 'nickserver/hkp/parse_key_info'
+require 'nickserver/hkp/key_info'
+
+module Nickserver::Hkp
+ #
+ # Fetch keys via HKP
+ # http://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
+ #
class Source < Nickserver::Source
-
def query(nick)
status, response = search(nick)
if status == 200
best = pick_best_key(response)
get_key_by_fingerprint(best.keyid, nick)
- elsif status != 404 # 404 means no key found and we proceed
+ elsif status != 404 # 404 means no key found and we proceed
Nickserver::Response.new(status, response)
end
end
@@ -27,7 +24,7 @@ module Nickserver; module Hkp
def search(nick)
status, response = client.get_key_infos_by_email(nick)
parser = ParseKeyInfo.new status, response
- return parser.status_for(nick), parser.response_for(nick)
+ [parser.status_for(nick), parser.response_for(nick)]
end
def get_key_by_fingerprint(fingerprint, nick = nil)
@@ -35,7 +32,7 @@ module Nickserver; module Hkp
if status == 200
Response.new nick, response
else
- Nickserver::Response.new status, "HKP Request failed"
+ Nickserver::Response.new status, 'HKP Request failed'
end
end
@@ -48,11 +45,11 @@ module Nickserver; module Hkp
# that is signed by the oldest key.
#
def pick_best_key(key_info_list)
- key_info_list.sort {|a,b| a.creationdate <=> b.creationdate}.last
+ key_info_list.sort_by(&:creationdate).last
end
def client
@client ||= Client.new(adapter)
end
end
-end; end
+end
diff --git a/lib/nickserver/hkp/v_index_response.rb b/lib/nickserver/hkp/v_index_response.rb
index 865d476..a44af51 100644
--- a/lib/nickserver/hkp/v_index_response.rb
+++ b/lib/nickserver/hkp/v_index_response.rb
@@ -9,7 +9,6 @@ require 'nickserver/hkp/key_info'
# So no need for memoization and making things more complex.
module Nickserver::Hkp
class VIndexResponse
-
# 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
@@ -29,14 +28,14 @@ module Nickserver::Hkp
end
def keys
- key_infos.reject { |key| error_for_key(key) }
+ key_infos.reject &:error
end
def msg
if errors.any?
error_messages.join "\n"
else
- "Could not fetch keyinfo."
+ 'Could not fetch keyinfo.'
end
end
@@ -53,13 +52,12 @@ module Nickserver::Hkp
end
def errors
- key_infos.map{|key| error_for_key(key) }.compact
+ key_infos.map { |key| error_for_key(key) }.compact
end
def error_messages
key_infos.map do |key|
- err = error_for_key(key)
- error_message(key, err)
+ error_message(key)
end.compact
end
@@ -75,22 +73,8 @@ module Nickserver::Hkp
end
end
- def error_message(key, err)
- "Ignoring key #{key.keyid} for #{nick}: #{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
+ def error_message(key)
+ "Ignoring key #{key.keyid} for #{nick}: #{key.error}" if key.error
end
end
end