From 21049be7f256a30ae897d6c3390574427a5eae7e Mon Sep 17 00:00:00 2001 From: reusserl Date: Mon, 9 Dec 2013 11:35:34 +0100 Subject: [PATCH] -patched helper.rb to use /etc/ssh/ssh_known_hosts also -patched helper.rb to use Net::SSH::KnownHosts insted of 'ssh-keygen -F' -patched helper.rb to increase performance -patched helper.rb to go forward even no hostkey was found -patched verifier.rb to skip verify if no hostkey is present --- lib/ssh/key/helper.rb | 49 +++++++++++++++++++++++++++++++++++++---- lib/ssh/key/verifier.rb | 1 + 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lib/ssh/key/helper.rb b/lib/ssh/key/helper.rb index 8f60abd..7762935 100644 --- a/lib/ssh/key/helper.rb +++ b/lib/ssh/key/helper.rb @@ -12,12 +12,15 @@ def add_key_file(path, passphrase=nil) # Add a public key from your known_hosts file def add_key_from_host(hostname) - hostkey = %x{ssh-keygen -F "#{hostname}"}.split("\n")[1].chomp.split(" ",2)[-1] rescue nil + hostkey = SSH::Key::Helper.known_host_key('/etc/ssh/ssh_known_hosts', hostname) if hostkey == nil - raise SSH::Key::KeyNotFound.new("Could not find host key '#{hostname}' " \ - "in known_hosts (using ssh-keygen -F)") + hostkey = SSH::Key::Helper.known_host_key('~/.ssh/known_hosts', hostname) + if hostkey == nil + SSH::Key::KeyNotFound.new("Could not find host key '#{hostname}' " \ + "in known_hosts file") + end end - @keys << Net::SSH::KeyFactory.load_data_public_key(hostkey) + @keys << hostkey end # Add a public key from a ublic key string @@ -25,4 +28,42 @@ def add_public_key_data(data) @logger.info "Adding key from data #{data}" @keys << Net::SSH::KeyFactory.load_data_public_key(data) end # def add_key_file + + def self.known_host_key(host_file, hostname) + @@known_hosts ||= {} + keys = @@known_hosts[host_file] ||= read_keys(host_file) + keys[hostname] + end + + # adapted from Net::SSH::KnownHosts#keys_for(host) + def self.read_keys(host_file) + keys = {} + return keys unless File.readable?(host_file) + + File.open(host_file) do |file| + scanner = StringScanner.new("") + file.each_line do |line| + scanner.string = line + + scanner.skip(/\s*/) + next if scanner.match?(/$|#/) + + hostlist = scanner.scan(/\S+/).split(/,/) + + scanner.skip(/\s*/) + type = scanner.scan(/\S+/) + + next unless Net::SSH::KnownHosts::SUPPORTED_TYPE.include?(type) + + scanner.skip(/\s*/) + blob = scanner.rest.unpack("m*").first + key = Net::SSH::Buffer.new(blob).read_key + + # only store first key + hostlist.each {|host| keys[host] ||= key } + end + end + + keys + end end; end; end # module SSH::Key::Helper diff --git a/lib/ssh/key/verifier.rb b/lib/ssh/key/verifier.rb index f2b52be..bff4374 100644 --- a/lib/ssh/key/verifier.rb +++ b/lib/ssh/key/verifier.rb @@ -99,6 +99,7 @@ def verify(signatures, original) inputs.each do |signature| identities.each do |identity| + next unless identity key = [signature, identity] results[key] = identity.ssh_do_verify(signature, original) @logger.info "Trying key #{identity.to_s.split("\n")[1]}... #{results[key]}"