Commit 1221bec5 authored by Douwe Maan's avatar Douwe Maan

Refactor key fingerprint generation.

parent e245547e
......@@ -16,7 +16,6 @@ require 'digest/md5'
class Key < ActiveRecord::Base
include Sortable
include Gitlab::Popen
belongs_to :user
......@@ -79,44 +78,9 @@ class Key < ActiveRecord::Base
def generate_fingerprint
self.fingerprint = nil
return unless key.present?
cmd_status = 0
cmd_output = ''
explicit_fingerprint_algorithm = false
Tempfile.open('gitlab_key_file') do |file|
file.puts key
file.rewind
# 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))
if version_status.zero?
out, _ = version_output.scan /.*?(\d)\.(\d).*?,/
major, minor = out[0], out[1]
if major.to_i > 6 or (major.to_i == 6 and minor.to_i >= 8)
explicit_fingerprint_algorithm = true
end
end
if explicit_fingerprint_algorithm
cmd_output, cmd_status = popen(%W(ssh-keygen -E md5 -lf #{file.path}), '/tmp')
else
cmd_output, cmd_status = popen(%W(ssh-keygen -lf #{file.path}), '/tmp')
end
end
if cmd_status.zero?
if explicit_fingerprint_algorithm
cmd_output.gsub /(MD5:)(\h{2}:)+\h{2}/ do |match|
match.slice! /^MD5:/
self.fingerprint = match
end
else
cmd_output.gsub /(\h{2}:)+\h{2}/ do |match|
self.fingerprint = match
end
end
end
return unless self.key.present?
self.fingerprint = Gitlab::KeyFingerprint.new(self.key).fingerprint
end
end
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_match = cmd_output.match(/(MD5:)?(?<fingerprint>(?:\h{2}:){15}\h{2})/)
return nil unless fingerprint_match
fingerprint_match[: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
require "spec_helper"
describe Gitlab::KeyFingerprint do
let(:key) { "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" }
let(:fingerprint) { "3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b" }
describe "#fingerprint" do
it "generates the key's fingerprint" do
expect(Gitlab::KeyFingerprint.new(key).fingerprint).to eq(fingerprint)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment