55 lines
1.4 KiB
Ruby
55 lines
1.4 KiB
Ruby
module Gitlab
|
|
class KeyFingerprint
|
|
include Gitlab::Popen
|
|
|
|
attr_accessor :key
|
|
|
|
def initialize(key)
|
|
@key = key
|
|
end
|
|
|
|
def fingerprint
|
|
cmd_status = 0
|
|
cmd_output = ''
|
|
|
|
Tempfile.open('gitlab_key_file') do |file|
|
|
file.puts key
|
|
file.rewind
|
|
|
|
cmd = []
|
|
cmd.push *%W(ssh-keygen)
|
|
cmd.push *%W(-E md5) if explicit_fingerprint_algorithm?
|
|
cmd.push *%W(-lf #{file.path})
|
|
|
|
cmd_output, cmd_status = popen(cmd, '/tmp')
|
|
end
|
|
|
|
return nil unless cmd_status.zero?
|
|
|
|
# 16 hex bytes separated by ':', optionally starting with "MD5:"
|
|
fingerprint_matches = cmd_output.match(/(MD5:)?(?<fingerprint>(\h{2}:){15}\h{2})/)
|
|
return nil unless fingerprint_matches
|
|
|
|
fingerprint_matches[:fingerprint]
|
|
end
|
|
|
|
private
|
|
|
|
def explicit_fingerprint_algorithm?
|
|
# OpenSSH 6.8 introduces a new default output format for fingerprints.
|
|
# Check the version and decide which command to use.
|
|
|
|
version_output, version_status = popen(%W(ssh -V))
|
|
return false unless version_status.zero?
|
|
|
|
version_matches = version_output.match(/OpenSSH_(?<major>\d+)\.(?<minor>\d+)/)
|
|
return false unless version_matches
|
|
|
|
version_info = Gitlab::VersionInfo.new(version_matches[:major].to_i, version_matches[:minor].to_i)
|
|
|
|
required_version_info = Gitlab::VersionInfo.new(6, 8)
|
|
|
|
version_info >= required_version_info
|
|
end
|
|
end
|
|
end
|