class SSHKit::Backend::Netssh::KnownHostsKeys

Attributes

hosts_hashes[RW]
hosts_keys[RW]
path[R]

Public Class Methods

new(path) click to toggle source
Calls superclass method
# File lib/sshkit/backends/netssh/known_hosts.rb, line 10
def initialize(path)
  super()
  @path = File.expand_path(path)
  @hosts_keys = nil
end

Public Instance Methods

keys_for(hostlist) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 16
def keys_for(hostlist)
  keys, hashes = hosts_keys, hosts_hashes
  parse_file unless keys && hashes
  keys, hashes = hosts_keys, hosts_hashes

  hostlist.split(',').each do |host|
    key_list = keys[host]
    return key_list if key_list

    hashes.each do |(hmac, salt), hash_keys|
      if OpenSSL::HMAC.digest(sha1, salt, host) == hmac
        return hash_keys
      end
    end
  end

  []
end

Private Instance Methods

empty_line?(scanner) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 89
def empty_line?(scanner)
  scanner.skip(/\s*/)
  scanner.match?(/$|#/)
end
parse_file() click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 44
def parse_file
  synchronize do
    return if hosts_keys && hosts_hashes

    unless File.readable?(path)
      self.hosts_keys = {}
      self.hosts_hashes = []
      return
    end

    new_keys = {}
    new_hashes = []
    File.open(path) do |file|
      scanner = StringScanner.new("")
      file.each_line do |line|
        scanner.string = line
        parse_line(scanner, new_keys, new_hashes)
      end
    end
    self.hosts_keys = new_keys
    self.hosts_hashes = new_hashes
  end
end
parse_host_hash(line) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 84
def parse_host_hash(line)
  _, _, salt, hmac = line.split('|')
  [Base64.decode64(hmac), Base64.decode64(salt)]
end
parse_hostlist(scanner) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 94
def parse_hostlist(scanner)
  scanner.skip(/\s*/)
  scanner.scan(/\S+/).split(',')
end
parse_key(scanner) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 104
def parse_key(scanner)
  scanner.skip(/\s*/)
  Net::SSH::Buffer.new(scanner.rest.unpack("m*").first).read_key
end
parse_line(scanner, hosts_keys, hosts_hashes) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 68
def parse_line(scanner, hosts_keys, hosts_hashes)
  return if empty_line?(scanner)

  hostlist = parse_hostlist(scanner)
  return unless supported_type?(scanner)
  key = parse_key(scanner)

  if hostlist.size == 1 && hostlist.first =~ /\A\|1(\|.+){2}\z/
    hosts_hashes << [parse_host_hash(hostlist.first), key]
  else
    hostlist.each do |host|
      (hosts_keys[host] ||= []) << key
    end
  end
end
sha1() click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 40
def sha1
  @sha1 ||= OpenSSL::Digest.new('sha1')
end
supported_type?(scanner) click to toggle source
# File lib/sshkit/backends/netssh/known_hosts.rb, line 99
def supported_type?(scanner)
  scanner.skip(/\s*/)
  Net::SSH::KnownHosts::SUPPORTED_TYPE.include?(scanner.scan(/\S+/))
end